Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive.pm URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive.pm?rev=726079&view=auto ============================================================================== --- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive.pm (added) +++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive.pm Fri Dec 12 10:20:10 2008 @@ -0,0 +1,84 @@ +#!/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: Predictive.pm 1945 2008-12-11 20:58:08Z fapeeler $ +############################################################################## + +=head1 NAME + +VCL::Module::Predictive - VCL predictive loading base module + +=head1 SYNOPSIS + + use base qw(VCL::Module::Predictive); + +=head1 DESCRIPTION + + Needs to be written. + +=cut + +############################################################################## +package VCL::Module::Predictive; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../.."; + +# Configure inheritance +use base qw(VCL::Module); + +# 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 + +#///////////////////////////////////////////////////////////////////////////// + +1; +__END__ + +=head1 BUGS and LIMITATIONS + + There are no known bugs in this module. + Please report problems to the VCL team ([email protected]). + +=head1 AUTHOR + + Aaron Peeler, [email protected] + Andy Kurth, [email protected] + +=head1 SEE ALSO + +L<http://vcl.ncsu.edu> + + +=cut
Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_0.pm URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_0.pm?rev=726079&view=auto ============================================================================== --- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_0.pm (added) +++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_0.pm Fri Dec 12 10:20:10 2008 @@ -0,0 +1,201 @@ +#!/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: Level_0.pm 1945 2008-12-11 20:58:08Z fapeeler $ +############################################################################## + +=head1 NAME + +VCL::Module::Predictive::Level_0 - VCL predictive loading module for "Level 0" algorithm + +=head1 SYNOPSIS + + use base qw(VCL::Module::Predictive::Level_0); + +=head1 DESCRIPTION + + Needs to be written. + +=cut + +############################################################################## +package VCL::Module::Predictive::Level_0; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../../.."; + +# Configure inheritance +use base qw(VCL::Module::Predictive); + +# 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 English '-no_match_vars'; + +use VCL::utils; + +############################################################################## + +=head1 OBJECT METHODS + +=cut + +#///////////////////////////////////////////////////////////////////////////// + +=head2 get_next_image + + Parameters : None. Must be called as an object method. + Returns : + Description : + +=cut + +sub get_next_image { + my $self = shift; + if (ref($self) !~ /Level_0/) { + notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method, process exiting"); + exit 1; + } + #notify($ERRORS{'WARNING'}, 0, "get_next_image_revision works!"); + + # Retrieve variables from the DataStructure + my $request_id = $self->data->get_request_id(); + my $reservation_id = $self->data->get_reservation_id(); + my $computer_id = $self->data->get_computer_id(); + my $computer_short_name = $self->data->get_computer_short_name(); + + my $notify_prefix = "predictive_reload_Level_0: "; + + notify($ERRORS{'OK'}, 0, "$notify_prefix for $computer_id"); + + my $select_statement = " + SELECT DISTINCT + req.start AS starttime, + ir.imagename AS imagename, + res.imagerevisionid AS imagerevisionid, + res.imageid AS imageid + FROM + reservation res, + request req, + image i, + state s, + imagerevision ir + WHERE + res.requestid = req.id + AND req.stateid = s.id + AND i.id = res.imageid + AND ir.id = res.imagerevisionid + AND res.computerid = $computer_id + AND (s.name = \'new\' OR s.name = \'reload\' OR s.name = \'imageprep\') + "; + + # Call the database select subroutine + # This will return an array of one or more rows based on the select statement + my @selected_rows = database_select($select_statement); + my @ret_array; + + # Check to make sure 1 or more rows were returned + if (scalar @selected_rows > 0) { + # Loop through list of upcoming reservations + # Based on the start time load the next one + + my $now = time(); + + # It contains a hash + for (@selected_rows) { + my %reservation_row = %{$_}; + # $reservation_row{starttime} + # $reservation_row{imagename} + # $reservation_row{imagerevisionid} + # $reservation_row{imageid} + my $epoch_start = convert_to_epoch_seconds($reservation_row{starttime}); + my $diff = $epoch_start - $now; + # If start time is less than 50 minutes from now return this image + notify($ERRORS{'OK'}, 0, "$notify_prefix diff= $diff image= $reservation_row{imagename} imageid=$reservation_row{imageid}"); + if ($diff < (50 * 60)) { + notify($ERRORS{'OK'}, 0, "$notify_prefix future reservation detected diff= $diff image= $reservation_row{imagename} imageid=$reservation_row{imageid}"); + push(@ret_array, $reservation_row{imagename}, $reservation_row{imageid}, $reservation_row{imagerevisionid}); + return @ret_array; + } + } ## end for (@selected_rows) + } ## end if (scalar @selected_rows > 0) + + # No upcoming reservations - fetch preferred image information + my $select_preferredimage = " + SELECT DISTINCT + imagerevision.imagename AS imagename, + imagerevision.id AS imagerevisionid, + image.id AS imageid + FROM + image, + computer, + imagerevision + WHERE + imagerevision.imageid = computer.preferredimageid + AND imagerevision.production = 1 + AND computer.preferredimageid = image.id + AND computer.id = $computer_id + "; + + # Call the database select subroutine + # This will return an array of one or more rows based on the select statement + my @preferred_selected_rows = database_select($select_preferredimage); + + # Check to make sure at least 1 row were returned + if (scalar @preferred_selected_rows == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computerid $computer_id"); + return 0; + } + elsif (scalar @preferred_selected_rows > 1) { + notify($ERRORS{'WARNING'}, 0, "" . scalar @preferred_selected_rows . " rows were returned from database select"); + return 0; + } + notify($ERRORS{'OK'}, 0, "$notify_prefix returning preferredimage image=$preferred_selected_rows[0]{imagename} imageid=$preferred_selected_rows[0]{imageid}"); + push(@ret_array, $preferred_selected_rows[0]{imagename}, $preferred_selected_rows[0]{imageid}, $preferred_selected_rows[0]{imagerevisionid}); + return @ret_array; + +} ## end sub get_next_image_revision + +#///////////////////////////////////////////////////////////////////////////// + +1; +__END__ + +=head1 BUGS and LIMITATIONS + + There are no known bugs in this module. + Please report problems to the VCL team ([email protected]). + +=head1 AUTHOR + + Aaron Peeler, [email protected] + Andy Kurth, [email protected] + +=head1 SEE ALSO + +L<http://vcl.ncsu.edu> + + +=cut Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_1.pm URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_1.pm?rev=726079&view=auto ============================================================================== --- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_1.pm (added) +++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Predictive/Level_1.pm Fri Dec 12 10:20:10 2008 @@ -0,0 +1,402 @@ +#!/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: Level_1.pm 1945 2008-12-11 20:58:08Z fapeeler $ +############################################################################## + +=head1 NAME + +VCL::Module::Predictive::Level_1 - VCL predictive loading module for "Level 1" algorithm + +=head1 SYNOPSIS + + use base qw(VCL::Module::Predictive::Level_1); + +=head1 DESCRIPTION + + Needs to be written. + +=cut + +############################################################################## +package VCL::Module::Predictive::Level_1; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../../.."; + +# Configure inheritance +use base qw(VCL::Module::Predictive); + +# 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 English '-no_match_vars'; + +use VCL::utils; + +############################################################################## + +=head1 OBJECT METHODS + +=cut + +#///////////////////////////////////////////////////////////////////////////// + +=head2 get_next_image + + Parameters : None. Must be called as an object method. + Returns : + Description : + +=cut + +sub get_next_image { + my $self = shift; + if (ref($self) !~ /Level_1/) { + notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method, process exiting"); + exit 1; + } + #notify($ERRORS{'WARNING'}, 0, "get_next_image_revision works!"); + + # Retrieve variables from the DataStructure + my $request_id = $self->data->get_request_id(); + my $reservation_id = $self->data->get_reservation_id(); + my $computer_id = $self->data->get_computer_id(); + my $computer_short_name = $self->data->get_computer_short_name(); + + my $notify_prefix = "predictive_reload_Level_1 :"; + + notify($ERRORS{'OK'}, 0, "$notify_prefix starting predictive_reload_level_1 for $computer_id"); + + my $select_statement = " + SELECT DISTINCT + req.start AS starttime, + ir.imagename AS imagename, + res.imagerevisionid AS imagerevisionid, + res.imageid AS imageid + FROM + reservation res, + request req, + image i, + state s, + imagerevision ir + WHERE + res.requestid = req.id + AND req.stateid = s.id + AND i.id = res.imageid + AND ir.id = res.imagerevisionid + AND res.computerid = $computer_id + AND (s.name = \'new\' OR s.name = \'reload\' OR s.name = \'imageprep\') + "; + + # Call the database select subroutine + # This will return an array of one or more rows based on the select statement + my @selected_rows = database_select($select_statement); + my @ret_array; + + # Check to make sure 1 or more rows were returned + if (scalar @selected_rows > 0) { + # Loop through list of upcoming reservations + # Based on the start time load the next one + + my $now = time(); + + # It contains a hash + for (@selected_rows) { + my %reservation_row = %{$_}; + # $reservation_row{starttime} + # $reservation_row{imagename} + # $reservation_row{imagerevisionid} + # $reservation_row{imageid} + my $epoch_start = convert_to_epoch_seconds($reservation_row{starttime}); + my $diff = $epoch_start - $now; + # If start time is less than 50 minutes from now return this image + notify($ERRORS{'OK'}, 0, "$notify_prefix diff= $diff image= $reservation_row{imagename} imageid=$reservation_row{imageid}"); + if ($diff < (50 * 60)) { + notify($ERRORS{'OK'}, 0, "$notify_prefix future reservation detected diff= $diff image= $reservation_row{imagename} imageid=$reservation_row{imageid}"); + push(@ret_array, $reservation_row{imagename}, $reservation_row{imageid}, $reservation_row{imagerevisionid}); + return @ret_array; + } + } ## end for (@selected_rows) + } ## end if (scalar @selected_rows > 0) + + # No upcoming reservations - determine most popular, unloaded image + + # determine state of system + + # get machine type + my $select_type = " + SELECT + type + FROM + computer + WHERE + id = $computer_id + "; + my @data = database_select($select_type); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my $type = $data[0]{type}; + + # online machines + my $select_online = " + SELECT + COUNT(id) as cnt + FROM + computer + WHERE + stateid IN (2, 3, 6, 8, 11) + AND type = '$type' + "; + @data = database_select($select_online); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my $online = $data[0]{cnt}; + + # available machines + my $select_available = " + SELECT + COUNT(id) AS cnt + FROM + computer + WHERE + stateid = 2 + AND type = '$type' + "; + @data = database_select($select_available); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my $avail = $data[0]{cnt}; + + # check if > 75% usage, look at past 2 days, otherwise, look at past 6 months + my $timeframe; + if (($avail / $online) > 0.75) { + $timeframe = '2 DAY'; + } + else { + $timeframe = '6 MONTH'; + } + + # what images map to this computer + my $select_mapped_images = " + SELECT + id + FROM + resource + WHERE + resourcetypeid = 12 + AND subid = $computer_id + "; + @data = database_select($select_mapped_images); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my $resourceid = $data[0]{id}; + + my $select_compgrps1 = " + SELECT + resourcegroupid + FROM + resourcegroupmembers + WHERE + resourceid = $resourceid + "; + @data = database_select($select_compgrps1); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my @compgroups; + foreach (@data) { + my %row = %{$_}; + push(@compgroups, $row{resourcegroupid}); + } + + my $inlist = join(',', @compgroups); + my $select_imggrps1 = " + SELECT + resourcegroupid2 + FROM + resourcemap + WHERE + resourcetypeid1 = 12 + AND resourcegroupid1 IN ($inlist) + AND resourcetypeid2 = 13 + "; + @data = database_select($select_imggrps1); + my @imggroups; + foreach (@data) { + my %row = %{$_}; + push(@imggroups, $row{resourcegroupid2}); + } + my $select_imggrps2 = " + SELECT + resourcegroupid1 + FROM + resourcemap + WHERE + resourcetypeid2 = 12 + AND resourcegroupid2 IN ($inlist) + AND resourcetypeid1 = 13 + "; + @data = database_select($select_imggrps2); + foreach (@data) { + my %row = %{$_}; + push(@imggroups, $row{resourcegroupid1}); + } + if (scalar @imggroups == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + + $inlist = join(',', @imggroups); + my $select_imageids = " + SELECT + DISTINCT(r.subid) + FROM + image i, + resource r, + resourcegroupmembers rgm + WHERE + rgm.resourceid = r.id + AND r.resourcetypeid = 13 + AND rgm.resourcegroupid IN ($inlist) + AND r.subid = i.id + AND i.deleted = 0 + "; + my @imgids; + @data = database_select($select_imageids); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + foreach (@data) { + my %row = %{$_}; + push(@imgids, $row{subid}); + } + + # which of those are loaded + $inlist = join(',', @imgids); + my $select_loaded = " + SELECT + DISTINCT(currentimageid) + FROM + computer + WHERE + currentimageid IN ($inlist) + AND stateid = 2"; + @data = database_select($select_loaded); + my @loaded; + foreach (@data) { + my %row = %{$_}; + push(@loaded, $row{currentimageid}); + } + + # which of those are not loaded (find difference of @imagids and @loaded) + my (@intersection, @notloaded, $element); + @intersection = @notloaded = (); + my %count = (); + foreach $element (@imgids, @loaded) {$count{$element}++} + foreach $element (keys %count) { + push @{$count{$element} > 1 ? \...@intersection : \...@notloaded}, $element; + } + + # get the most popular in $timeframe + $inlist = join(',', @notloaded); + my $select_imageid = " + SELECT + COUNT(imageid) AS cnt, + imageid + FROM + log + WHERE + imageid IN ($inlist) + AND start > (NOW() - INTERVAL $timeframe) + GROUP BY imageid + ORDER BY cnt DESC + LIMIT 1 + "; + @data = database_select($select_imageid); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + my $imageid = $data[0]{imageid}; + + # get extra data about the image + my $select_extra = " + SELECT + i.name, + r.id + FROM + image i, + imagerevision r + WHERE + i.id = $imageid + AND r.imageid = $imageid + AND r.production = 1 + "; + @data = database_select($select_extra); + if (scalar @data == 0) { + notify($ERRORS{'WARNING'}, 0, "$notify_prefix failed to fetch preferred image for computer_id $computer_id"); + return 0; + } + + + notify($ERRORS{'OK'}, 0, "$notify_prefix $computer_id $data[0]{name}, $imageid, $data[0]{id}"); + push(@ret_array, $data[0]{name}, $imageid, $data[0]{id}); + return @ret_array; + + +} ## end sub get_next_image_revision + +#///////////////////////////////////////////////////////////////////////////// + +1; +__END__ + +=head1 BUGS and LIMITATIONS + + There are no known bugs in this module. + Please report problems to the VCL team ([email protected]). + +=head1 AUTHOR + + Aaron Peeler, [email protected] + Andy Kurth, [email protected] + +=head1 SEE ALSO + +L<http://vcl.ncsu.edu> + + +=cut Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning.pm URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning.pm?rev=726079&view=auto ============================================================================== --- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning.pm (added) +++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning.pm Fri Dec 12 10:20:10 2008 @@ -0,0 +1,84 @@ +#!/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: Provisioning.pm 1953 2008-12-12 14:23:17Z arkurth $ +############################################################################## + +=head1 NAME + +VCL::Module::Provisioning - VCL provisioning base module + +=head1 SYNOPSIS + + use base qw(VCL::Module::Provisioning); + +=head1 DESCRIPTION + + Needs to be written. + +=cut + +############################################################################## +package VCL::Module::Provisioning; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../.."; + +# Configure inheritance +use base qw(VCL::Module); + +# 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 + +#///////////////////////////////////////////////////////////////////////////// + +1; +__END__ + +=head1 BUGS and LIMITATIONS + + There are no known bugs in this module. + Please report problems to the VCL team ([email protected]). + +=head1 AUTHOR + + Aaron Peeler, [email protected] + Andy Kurth, [email protected] + +=head1 SEE ALSO + +L<http://vcl.ncsu.edu> + + +=cut Added: incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/Lab.pm URL: http://svn.apache.org/viewvc/incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/Lab.pm?rev=726079&view=auto ============================================================================== --- incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/Lab.pm (added) +++ incubator/vcl/tags/import/managementnode/lib/VCL/Module/Provisioning/Lab.pm Fri Dec 12 10:20:10 2008 @@ -0,0 +1,311 @@ +#!/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: Lab.pm 1953 2008-12-12 14:23:17Z arkurth $ +############################################################################## + +=head1 NAME + +VCL::Provisioning::Lab - VCL module to support povisioning of lab machines + +=head1 SYNOPSIS + + Needs to be written + +=head1 DESCRIPTION + + This module provides... + +=cut + +############################################################################## +package VCL::Module::Provisioning::Lab; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../../.."; + +# Configure inheritance +use base qw(VCL::Module::Provisioning); + +# 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 initialize + + Parameters : + Returns : + Description : + +=cut + +sub initialize { + my $self = shift; + my $request_id = $self->data->get_request_id(); + my $reservation_id = $self->data->get_reservation_id(); + my $reservation_is_parent = $self->data->is_parent_reservation; + my $request_check_time = $self->data->get_request_check_time(); + my $computer_id = $self->data->get_computer_id(); + + notify($ERRORS{'OK'}, 0, "initializing Lab module, computer id: $computer_id, is parent reservation: $reservation_is_parent"); + + # Check if this is a preload request + # Nothing needs to be done for lab preloads + if ($request_check_time eq 'preload') { + notify($ERRORS{'OK'}, 0, "check_time result is $request_check_time, nothing needs to be done for lab preloads"); + + insertloadlog($reservation_id, $computer_id, "info", "lab preload does not need to be processed"); + + # Only the parent reservation should update the preload flag + if ($reservation_is_parent) { + # Set the preload flag back to 1 so it will be processed again + if (update_preload_flag($request_id, 1)) { + notify($ERRORS{'OK'}, 0, "parent reservation: updated preload flag to 1"); + insertloadlog($reservation_id, $computer_id, "info", "request preload flag updated to 1"); + } + else { + notify($ERRORS{'WARNING'}, 0, "parent reservation: failed to update preload flag to 1"); + insertloadlog($reservation_id, $computer_id, "info", "failed to update request preload flag to 1"); + } + } + else { + notify($ERRORS{'OK'}, 0, "child reservation: request preload flag will be changed by the parent reservation"); + } + notify($ERRORS{'OK'}, 0, "preload lab reservation process exiting"); + exit; + } + else { + notify($ERRORS{'OK'}, 0, "check_time result is $request_check_time, reservation will be processed"); + } +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 node_status + + Parameters : [0]: computer node name (optional) + [1]: log file path (optional) + Returns : Depends on the context which node_status was called: + default: string containing "READY" or "FAIL" + boolean: true if ping, SSH, and VCL client checks are successful + false if any checks fail + list: array, values are 1 for SUCCESS, 0 for FAIL + [0]: Node status ("READY" or "FAIL") + [1]: Ping status (0 or 1) + [2]: SSH status (0 or 1) + [3]: VCL client daemon status (0 ir 1) + arrayref: reference to array described above + hashref: reference to hash with keys/values: + {status} => <"READY","FAIL"> + {ping} => <0,1> + {ssh} => <0,1> + {vcl_client} => <0,1> + Description : Checks the status of a lab machine. Checks if the machine is + pingable, can be accessed via SSH, and the VCL client is running. + +=cut + +sub node_status { + my $self = shift; + my ($computer_node_name, $log); + + my ($management_node_os_name, $management_node_keys, $computer_host_name, $computer_short_name, $computer_ip_address, $image_os_name); + + # Check if subroutine was called as a class method + if (ref($self) !~ /lab/i) { + #$cidhash->{hostname}, $cidhash->{OSname}, $cidhash->{MNos}, $cidhash->{IPaddress}, $identity, $LOG) + $computer_node_name = $self; + $image_os_name = shift; + $management_node_os_name = shift; + $computer_ip_address = shift; + $management_node_keys = shift; + $log = shift; + + $log = 0 if !$log; + $computer_short_name = $1 if ($computer_node_name =~ /([-_a-zA-Z0-9]*)(\.?)/); + } ## end if (ref($self) !~ /lab/i) + else { + # Get the computer name from the DataStructure + $computer_node_name = $self->data->get_computer_node_name(); + + # Check if this was called as a class method, but a node name was also specified as an argument + my $node_name_argument = shift; + $computer_node_name = $node_name_argument if $node_name_argument; + $management_node_os_name = $self->data->get_management_node_os_name(); + $management_node_keys = $self->data->get_management_node_keys(); + $computer_host_name = $self->data->get_computer_host_name(); + $computer_short_name = $self->data->get_computer_short_name(); + $computer_ip_address = $self->data->get_computer_ip_address(); + $image_os_name = $self->data->get_image_os_name(); + $log = 0; + } ## end else [ if (ref($self) !~ /lab/i) + + notify($ERRORS{'OK'}, $log, "computer_short_name= $computer_short_name "); + notify($ERRORS{'OK'}, $log, "computer_node_name= $computer_node_name "); + notify($ERRORS{'OK'}, $log, "image_os_name= $image_os_name"); + notify($ERRORS{'OK'}, $log, "management_node_os_name= $management_node_os_name"); + notify($ERRORS{'OK'}, $log, "computer_ip_address= $computer_ip_address"); + notify($ERRORS{'OK'}, $log, "management_node_keys= $management_node_keys"); + + + # Check the node name variable + if (!$computer_node_name) { + notify($ERRORS{'WARNING'}, 0, "node name could not be determined"); + return 0; + } + notify($ERRORS{'DEBUG'}, $log, "checking status of node: $computer_node_name"); + + $computer_host_name = $computer_node_name; + + # Create a hash to store status components + my %status; + + # Initialize all hash keys here to make sure they're defined + $status{status} = 0; + $status{ping} = 0; + $status{ssh} = 0; + $status{vcl_client} = 0; + + # Check if host is listed in management node's known_hosts file + notify($ERRORS{'DEBUG'}, $log, "checking if $computer_host_name in management node known_hosts file"); + if (known_hosts($computer_host_name, $management_node_os_name, $computer_ip_address)) { + notify($ERRORS{'OK'}, $log, "$computer_host_name public key added to management node known_hosts file"); + } + else { + notify($ERRORS{'WARNING'}, $log, "failed to add $computer_host_name public key to management node known_hosts"); + } + + + # Check if node is pingable + notify($ERRORS{'DEBUG'}, $log, "checking if $computer_ip_address is pingable"); + if (_pingnode($computer_ip_address)) { + notify($ERRORS{'OK'}, $log, "$computer_ip_address is pingable"); + $status{ping} = 1; + } + else { + notify($ERRORS{'WARNING'}, $log, "$computer_ip_address is not pingable"); + $status{ping} = 0; + } + + + # Check if sshd is open on the admin port (24) + notify($ERRORS{'DEBUG'}, $log, "checking if $computer_ip_address sshd admin port 24 is accessible"); + if (check_ssh($computer_ip_address, 24, $log)) { + notify($ERRORS{'OK'}, $log, "$computer_ip_address admin sshd port 24 is accessible"); + + # Run uname -n to make sure ssh is usable + notify($ERRORS{'OK'}, $log, "checking if ssh command can be run on $computer_ip_address"); + my ($uname_exit_status, $uname_output) = run_ssh_command($computer_ip_address, $management_node_keys, "uname -n", "vclstaff", 24); + if (!defined($uname_output) || !$uname_output) { + notify($ERRORS{'WARNING'}, $log, "unable to run 'uname -n' ssh command on $computer_ip_address"); + $status{ssh} = 0; + } + else { + notify($ERRORS{'OK'}, $log, "successfully ran 'uname -n' ssh command on $computer_ip_address"); + $status{ssh} = 1; + } + + ## Check the uname -n output lines, make sure computer name is listed + #if (grep /$computer_short_name/, @{$uname_output}) { + # notify($ERRORS{'OK'}, $log, "found computer name in ssh 'uname -n' output"); + # #$status{ssh} = 1; + #} + #else { + # my $uname_output_string = join("\n", @{$uname_output}); + # notify($ERRORS{'WARNING'}, $log, "unable to find computer name in ssh 'uname -n' output output:\n$uname_output_string"); + # #$status{ssh} = 0; + #} + + # Check if is VCL client daemon is running + notify($ERRORS{'OK'}, $log, "checking if VCL client daemon is running on $computer_ip_address"); + my ($pgrep_exit_status, $pgrep_output) = run_ssh_command($computer_ip_address, $management_node_keys, "pgrep vclclient", "vclstaff", 24); + if (!defined($pgrep_output) || !$pgrep_output) { + notify($ERRORS{'WARNING'}, $log, "unable to run 'pgrep vclclient' command on $computer_ip_address"); + $status{vcl_client} = 0; + } + + # Check the pgrep output lines, make sure process is listed + if (grep /[0-9]+/, @{$pgrep_output}) { + notify($ERRORS{'DEBUG'}, $log, "VCL client daemon is running"); + $status{vcl_client} = 1; + } + else { + my $pgrep_output_string = join("\n", @{$pgrep_output}); + notify($ERRORS{'WARNING'}, $log, "VCL client daemon is not running, unable to find running process in 'pgrep vclclient' output:\n$pgrep_output_string"); + $status{vcl_client} = 0; + } + } ## end if (check_ssh($computer_ip_address, 24, $log... + else { + notify($ERRORS{'WARNING'}, $log, "$computer_ip_address sshd admin port 24 is not accessible"); + $status{ssh} = 0; + $status{vcl_client} = 0; + } + + # Determine the overall machine status based on the individual status results + if ($status{ping} && $status{ssh} && $status{vcl_client}) { + $status{status} = 'READY'; + } + else { + # Lab machine is not available, return undefined to indicate error occurred + notify($ERRORS{'WARNING'}, 0, "lab machine $computer_host_name ($computer_ip_address) is not available"); + return; + } + + notify($ERRORS{'OK'}, 0, "returning node status hash reference with {status}=$status{status}"); + return \%status; +} ## end sub node_status + +1; + +#///////////////////////////////////////////////////////////////////////////// + +__END__ + +=head1 BUGS and LIMITATIONS + + There are no known bugs in this module. + Please report problems to the VCL team ([email protected]). + +=head1 AUTHOR + + Aaron Peeler, [email protected] + Andy Kurth, [email protected] + +=head1 SEE ALSO + +L<http://vcl.ncsu.edu> + + +=cut
