mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-21 19:22:05 +00:00
307 lines
8.1 KiB
Perl
307 lines
8.1 KiB
Perl
# IBM(c) 2016 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
#-------------------------------------------------------
|
|
|
|
=head1
|
|
|
|
xCAT plugin to support z/VM (s390x) diagnostics command
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
package xCAT_plugin::zvmdiagnostics;
|
|
|
|
#use xCAT::Client;
|
|
use xCAT::zvmUtils;
|
|
|
|
#use xCAT::zvmCPUtils;
|
|
#use xCAT::MsgUtils;
|
|
use Sys::Hostname;
|
|
|
|
#use xCAT::Table;
|
|
#use xCAT::Utils;
|
|
#use xCAT::TableUtils;
|
|
#use xCAT::ServiceNodeUtils;
|
|
#use xCAT::NetworkUtils;
|
|
#use XML::Simple;
|
|
#use File::Basename;
|
|
#use File::Copy;
|
|
#use File::Path;
|
|
#use File::Temp;
|
|
use Time::HiRes;
|
|
use POSIX;
|
|
use Getopt::Long;
|
|
use strict;
|
|
use warnings;
|
|
|
|
#use Cwd;
|
|
# Set $DEBUGGING = 1 to get extra message logging
|
|
my $DEBUGGING = 0;
|
|
|
|
# Common prefix for log messages
|
|
my $ROUTINE = "zvmdiagnostics";
|
|
my $COMMAND = "diagnostics";
|
|
|
|
my $NOTIFY_FILENAME = "/var/lib/sspmod/appliance_system_role";
|
|
my $NOTIFY_KEYWORD = "notify";
|
|
my $NOTIFY_KEYWORD_DELIMITER = "=";
|
|
|
|
# If the following line ("1;") is not included, you get:
|
|
# /opt/xcat/lib/perl/xCAT_plugin/... did not return a true value
|
|
# where ... is the name of this file
|
|
1;
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 handled_commands
|
|
|
|
Return list of commands handled by this plugin
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub handled_commands {
|
|
return { $COMMAND => $ROUTINE, };
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 preprocess_request
|
|
|
|
Check and setup for hierarchy
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub preprocess_request {
|
|
my $req = shift;
|
|
my $callback = shift;
|
|
my $SUBROUTINE = "preprocess_request";
|
|
|
|
# Hash array
|
|
my %sn;
|
|
|
|
# Scalar variable
|
|
my $sn;
|
|
|
|
# Array
|
|
my @requests;
|
|
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE entry");
|
|
}
|
|
|
|
# If already preprocessed, go straight to request
|
|
if ( $req->{_xcatpreprocessed}->[0] == 1 ) {
|
|
return [$req];
|
|
}
|
|
my $nodes = $req->{node};
|
|
my $service = "xcat";
|
|
|
|
# Find service nodes for requested nodes
|
|
# Build an individual request for each service node
|
|
if ($nodes) {
|
|
$sn = xCAT::ServiceNodeUtils->get_ServiceNode( $nodes, $service, "MN" );
|
|
|
|
# Build each request for each service node
|
|
foreach my $snkey ( keys %$sn ) {
|
|
my $n = $sn->{$snkey};
|
|
print "snkey=$snkey, nodes=@$n\n";
|
|
my $reqcopy = {%$req};
|
|
$reqcopy->{node} = $sn->{$snkey};
|
|
$reqcopy->{'_xcatdest'} = $snkey;
|
|
$reqcopy->{_xcatpreprocessed}->[0] = 1;
|
|
push @requests, $reqcopy;
|
|
}
|
|
|
|
return \@requests;
|
|
}
|
|
else {
|
|
|
|
# Input error
|
|
my %rsp;
|
|
my $rsp;
|
|
$rsp->{data}->[0] =
|
|
"Input noderange missing. Usage: $ROUTINE <noderange> \n";
|
|
xCAT::MsgUtils->message( "I", $rsp, $callback, 0 );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 process_request
|
|
|
|
Process the command. This is the main call.
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub process_request {
|
|
my $SUBROUTINE = "process_request";
|
|
my $request = shift;
|
|
my $callback = shift;
|
|
my $nodes = $request->{node};
|
|
my $command = $request->{command}->[0];
|
|
my $args = $request->{arg};
|
|
my $envs = $request->{env};
|
|
$::STDIN = $request->{stdin}->[0];
|
|
my %rsp;
|
|
my $rsp;
|
|
my @nodes = @$nodes;
|
|
my $host = hostname();
|
|
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE entry");
|
|
}
|
|
|
|
# Process ID for xfork()
|
|
my $pid;
|
|
|
|
# Child process IDs
|
|
my @children = ();
|
|
|
|
#*** Collect or manage diagnostics***
|
|
if ( $command eq $COMMAND ) {
|
|
foreach (@nodes) {
|
|
$pid = xCAT::Utils->xfork();
|
|
|
|
# Parent process
|
|
if ($pid) {
|
|
push( @children, $pid );
|
|
}
|
|
|
|
# Child process
|
|
elsif ( $pid == 0 ) {
|
|
if ( xCAT::zvmUtils->isHypervisor($_) ) {
|
|
#TODO should this be handled inside the subroutine, ala rmvm?
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE for hypervisor - semantically coherent?");
|
|
}
|
|
}
|
|
else {
|
|
collectDiags( $callback, $_, $args );
|
|
}
|
|
|
|
# Exit process
|
|
exit(0);
|
|
}
|
|
else {
|
|
|
|
# Ran out of resources
|
|
die "Error: Could not fork\n";
|
|
}
|
|
|
|
} # End of foreach
|
|
} # End of case
|
|
|
|
# Wait for all processes to end
|
|
foreach (@children) {
|
|
waitpid( $_, 0 );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
|
|
=head3 collectDiags
|
|
|
|
Description : Collect diagnostics
|
|
Arguments : Node to collect diagnostics about
|
|
Returns : Nothing
|
|
Example : collectDiags($callback, $node);
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------
|
|
sub collectDiags {
|
|
my $SUBROUTINE = "collectDiags";
|
|
|
|
# Get inputs
|
|
my ( $callback, $node, $args ) = @_;
|
|
my $rc;
|
|
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE entry");
|
|
}
|
|
|
|
# Get node properties from 'zvm' table
|
|
my @propNames = ( 'hcp', 'userid', 'discovered' );
|
|
my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames );
|
|
|
|
# Get zHCP
|
|
my $hcp = $propVals->{'hcp'};
|
|
if ( !$hcp ) {
|
|
xCAT::zvmUtils->printLn( $callback, "$node: (Error) Missing node HCP" );
|
|
return;
|
|
}
|
|
|
|
# Get node user ID
|
|
my $userId = $propVals->{'userid'};
|
|
if ( !$userId ) {
|
|
xCAT::zvmUtils->printLn( $callback, "$node: (Error) Missing user ID" );
|
|
return;
|
|
}
|
|
|
|
# Capitalize user ID
|
|
$userId =~ tr/a-z/A-Z/;
|
|
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE sudoer:$::SUDOER zHCP:$hcp sudo:$::SUDO userid:$::userId");
|
|
}
|
|
my $out;
|
|
|
|
my $requestId = "NoUpstreamRequestID";
|
|
my $objectId = "NoUpstreamObjectID";
|
|
my $projectName = "NoUpstreamProjectName";
|
|
my $userUuid = "NoUpstreamUserUuid";
|
|
if ($args) {
|
|
@ARGV = @$args;
|
|
xCAT::zvmUtils->printSyslog(
|
|
"$ROUTINE $SUBROUTINE for node:$node on zhcp:$hcp args @$args");
|
|
|
|
# Parse options
|
|
GetOptions(
|
|
'requestid=s' => \$requestId # Optional
|
|
, 'objectid=s' => \$objectId # Optional
|
|
);
|
|
}
|
|
|
|
my $xcatnotify = "OPERATOR"; # Default value
|
|
my $xcatnotify_found = 0; # Not found yet
|
|
my (@array, $varname);
|
|
open( FILE, "<$NOTIFY_FILENAME" );
|
|
#TODO If file not found ("should never happen"), log error but continue
|
|
while (<FILE>) {
|
|
# Find record in file with NOTIFY=something on it, optionally delimited with whitespace
|
|
next unless ( /^[\s]*$NOTIFY_KEYWORD[\s]*$NOTIFY_KEYWORD_DELIMITER[\s]*(\S+)[\s]*$/i );
|
|
$xcatnotify_found = 1;
|
|
$xcatnotify = $1; # First parenthesized expression in regex above, that is: \S+
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE xCAT will notify $xcatnotify.");
|
|
}
|
|
last; # Ignore anything past the first matching record. Absent a bug elsewhere, there is only one value to find.
|
|
}
|
|
close(FILE);
|
|
if (not $xcatnotify_found) {
|
|
xCAT::zvmUtils->printSyslog(
|
|
"$ROUTINE $SUBROUTINE error: failed to parse $NOTIFY_KEYWORD$NOTIFY_KEYWORD_DELIMITER " .
|
|
"from $NOTIFY_FILENAME, defaulting to notify $xcatnotify");
|
|
}
|
|
#TODO add COZ... message ID
|
|
my $msg = "vmcp MSG $xcatnotify deployment failed: node $node userid $userId on zHCP $hcp";
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE $msg");
|
|
system($msg);
|
|
#TODO check system()'s rc
|
|
|
|
#TODO Capture diagnostic files
|
|
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE ... rest of implementation stubbed out ");
|
|
|
|
if ( $DEBUGGING == 1 ) {
|
|
xCAT::zvmUtils->printSyslog("$ROUTINE $SUBROUTINE exit");
|
|
}
|
|
return;
|
|
}
|
|
|