| #!/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 (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 |