diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index a906d6b78..5f323804e 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -6520,4 +6520,44 @@ sub isSELINUX #------------------------------------------------------------------------------- + +#-------------------------------------------------------------------------------- +=head3 pingNodeStatus + This function takes an array of nodes and returns their status using fping. + Arguments: + nodes-- an array of nodes. + Returns: + a hash that has the node status. The format is: + {alive=>[node1, node3,...], unreachable=>[node4, node2...]} +=cut +#-------------------------------------------------------------------------------- +sub pingNodeStatus { + my ($class, @mon_nodes)=@_; + my %status=(); + my @active_nodes=(); + my @inactive_nodes=(); + if ((@mon_nodes)&& (@mon_nodes > 0)) { + #get all the active nodes + my $nodes= join(' ', @mon_nodes); + my $temp=`fping -a $nodes 2> /dev/null`; + chomp($temp); + @active_nodes=split(/\n/, $temp); + + #get all the inactive nodes by substracting the active nodes from all. + my %temp2; + if ((@active_nodes) && ( @active_nodes > 0)) { + foreach(@active_nodes) { $temp2{$_}=1}; + foreach(@mon_nodes) { + if (!$temp2{$_}) { push(@inactive_nodes, $_);} + } + } + else {@inactive_nodes=@mon_nodes;} + } + + $status{$::STATUS_ACTIVE}=\@active_nodes; + $status{$::STATUS_INACTIVE}=\@inactive_nodes; + + return %status; +} + 1; diff --git a/xCAT-server/lib/xcat/monitoring/monitorctrl.pm b/xCAT-server/lib/xcat/monitoring/monitorctrl.pm index c565eae72..6876ee406 100644 --- a/xCAT-server/lib/xcat/monitoring/monitorctrl.pm +++ b/xCAT-server/lib/xcat/monitoring/monitorctrl.pm @@ -203,6 +203,7 @@ sub sendMonSignal { 0 means local host only. 2 means both local host and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: A hash table keyed by the plug-in names. The value is an array pointer pointer to a return code and message pair. For example: @@ -218,6 +219,7 @@ sub startMonitoring { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; refreshProductList(); @@ -230,7 +232,7 @@ sub startMonitoring { #print "product_names=@product_names\n"; my %ret=(); - print "-------startMonitoring: product_names=@product_names\n"; + #print "-------startMonitoring: product_names=@product_names\n"; foreach(@product_names) { my $aRef=$PRODUCT_LIST{$_}; if ($aRef) { @@ -239,7 +241,7 @@ sub startMonitoring { undef $SIG{CHLD}; #initialize and start monitoring no strict "refs"; - my @ret1 = ${$module_name."::"}{start}->($noderef, $scope, $callback); + my @ret1 = ${$module_name."::"}{start}->($noderef, $scope, $callback,$grands); $ret{$_}=\@ret1; } else { $ret{$_}=[1, "Monitoring plug-in module $_ is not registered or enabled."]; @@ -264,6 +266,7 @@ sub startMonitoring { 0 means local host only. 2 means both local host and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: (return_code, error_message) @@ -277,11 +280,12 @@ sub startNodeStatusMonitoring { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; refreshProductList(); if (!$pname) {$pname=$NODESTAT_MON_NAME;} - print "----startNodeStatusMonitoring: pname=$pname\n"; + #print "----startNodeStatusMonitoring: pname=$pname\n"; if ($pname) { my $aRef=$PRODUCT_LIST{$pname}; @@ -290,12 +294,12 @@ sub startNodeStatusMonitoring { undef $SIG{CHLD}; no strict "refs"; my $method = ${$module_name."::"}{supportNodeStatusMon}->(); - print "method=$method\n"; + #print "method=$method\n"; # return value 0 means not support. 1 means yes. if ($method > 0) { #start nodes tatus monitoring no strict "refs"; - my @ret2 = ${$module_name."::"}{startNodeStatusMon}->($noderef, $scope, $callback); + my @ret2 = ${$module_name."::"}{startNodeStatusMon}->($noderef, $scope, $callback,$grands); return @ret2; } else { @@ -325,6 +329,7 @@ sub startNodeStatusMonitoring { 0 means local host only. 2 means both local host and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: A hash table keyed by the plug-in names. The value is ann array pointer pointer to a return code and message pair. For example: @@ -340,6 +345,7 @@ sub stopMonitoring { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; #refreshProductList(); @@ -350,7 +356,7 @@ sub stopMonitoring { if (@product_names == 0) { @product_names=keys(%PRODUCT_LIST); } - print "-------stopMonitoring: product_names=@product_names\n"; + #print "-------stopMonitoring: product_names=@product_names\n"; my %ret=(); @@ -381,7 +387,7 @@ sub stopMonitoring { #stop monitoring undef $SIG{CHLD}; no strict "refs"; - my @ret2 = ${$module_name."::"}{stop}->($noderef, $scope, $callback); + my @ret2 = ${$module_name."::"}{stop}->($noderef, $scope, $callback,$grands); $ret{$_}=\@ret2; } @@ -403,6 +409,7 @@ sub stopMonitoring { 0 means local host only. 2 means both local host and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: (return_code, error_message) @@ -416,6 +423,7 @@ sub stopNodeStatusMonitoring { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; #refreshProductList(); if (!$pname) {$pname=$NODESTAT_MON_NAME;} @@ -440,7 +448,7 @@ sub stopNodeStatusMonitoring { #} } no strict "refs"; - my @ret2 = ${$module_name."::"}{stopNodeStatusMon}->($noderef, $scope, $callback); + my @ret2 = ${$module_name."::"}{stopNodeStatusMon}->($noderef, $scope, $callback,$grands); return @ret2; } } @@ -1229,6 +1237,7 @@ sub getAllRegs 0 means local host only. 2 means both local host and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: ret a hash with plug-in name as the keys and the an arry of [return code, error message] as the values. @@ -1242,6 +1251,7 @@ sub config { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; my %ret=(); my @product_names=@$nameref; @@ -1251,7 +1261,7 @@ sub config { @product_names=keys(%all); } - print "------config: product_names=@product_names\n"; + #print "------config: product_names=@product_names\n"; foreach(@product_names) { if (exists($all{$_})) { @@ -1268,7 +1278,7 @@ sub config { #initialize and start monitoring no strict "refs"; if (defined(${$module_name."::"}{config})) { - my @ret1 = ${$module_name."::"}{config}->($noderef, $scope, $callback); + my @ret1 = ${$module_name."::"}{config}->($noderef, $scope, $callback, $grands); $ret{$_}=\@ret1; } } else { @@ -1291,6 +1301,7 @@ sub config { 0 means local host only. 2 means both loca lhost and nodes, callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer. key: "servicenode,xcatmaset", value: a array pointer of grand children nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. Returns: ret a hash with plug-in name as the keys and the an arry of [return code, error message] as the values. @@ -1304,6 +1315,7 @@ sub deconfig { my $noderef=shift, my $scope=shift; my $callback=shift; + my $grands=shift; my @product_names=@$nameref; @@ -1312,7 +1324,7 @@ sub deconfig { if (@product_names == 0) { @product_names=keys(%all); } - print "------deconfig: product_names=@product_names\n"; + #print "------deconfig: product_names=@product_names\n"; foreach(@product_names) { @@ -1330,7 +1342,7 @@ sub deconfig { #initialize and start monitoring no strict "refs"; if (defined(${$module_name."::"}{deconfig})) { - my @ret1 = ${$module_name."::"}{deconfig}->($noderef, $scope, $callback); + my @ret1 = ${$module_name."::"}{deconfig}->($noderef, $scope, $callback, $grands); $ret{$_}=\@ret1; } } else { diff --git a/xCAT-server/lib/xcat/monitoring/nagiosmon.pm b/xCAT-server/lib/xcat/monitoring/nagiosmon.pm new file mode 100644 index 000000000..a897323d5 --- /dev/null +++ b/xCAT-server/lib/xcat/monitoring/nagiosmon.pm @@ -0,0 +1,1452 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_monitoring::nagiosmon; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; +use strict; +use File::Copy qw/copy cp mv move/; +use xCAT::NodeRange; +use Sys::Hostname; +use xCAT::Utils; +use xCAT::GlobalDef; +use xCAT_monitoring::monitorctrl; +use xCAT::MsgUtils; +use xCAT::DBobjUtils; +use Data::Dumper; +1; + + +#------------------------------------------------------------------------------- +=head1 xCAT_monitoring:nagiosmon +=head2 Package Description + xCAT monitoring plugin package to handle Nagios monitoring. +=cut +#------------------------------------------------------------------------------- + +#-------------------------------------------------------------------------------- +=head3 start + This function gets called by the monitorctrl module + when xcatd starts and when monstart command is issued by the user. + It starts the daemons and does necessary startup process for the Nagios monitoring. + p_nodes -- a pointer to an arrays of nodes to be monitored. null means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means both localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (return code, message) + if the callback is set, use callback to display the status and error. +=cut +#-------------------------------------------------------------------------------- +sub start { + print "nagiosmon::start called\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + my $grands=shift; + + my $localhostname=hostname(); + + #only start once. this function will get called twice for mn, once for children and once for grand children. + if (($grands) && (keys(%$grands) > 0)) { + return (0, "ok"); + } + + + my $isSN=xCAT::Utils->isServiceNode(); + + my $mychildren_cfg="/etc/nagios/objects/mychildren.cfg"; + if ($isSN) { #start nagios daemon only when mychildren exists on the sn + if (-f $mychildren_cfg) { + my $rc=`service nagios restart 2>&1`; + reportError("$localhostname: $rc", $callback); + } + } + else { #always start nagios daemon on mn + my $rc=`service nagios restart 2>&1`; + reportError("$localhostname: $rc", $callback); + } + + #go to nodes to start nrpe + my $inactive_nodes=[]; + if (($scope) && ($noderef)) { + my @mon_nodes=@$noderef; + my %nodes_status=xCAT::Utils->pingNodeStatus(@mon_nodes); + $inactive_nodes=$nodes_status{$::STATUS_INACTIVE}; + if (@$inactive_nodes>0) { + my $error="The following nodes cannot have nrpe started because they are inactive:\n @$inactive_nodes."; + reportError("$localhostname: $error", $callback); + } + + my $active_nodes=$nodes_status{$::STATUS_ACTIVE}; + if (@$active_nodes > 0) { + my $nodelist=join(',',@$active_nodes); + my $result=`XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodelist "service nrpe restart" 2>&1`; + if ($?) { + reportError("$localhostname: $result", $callback); + return (1, $result); + } + + } + } + + return (0, "started"); +} + + + +#-------------------------------------------------------------------------------- +=head3 stop + This function gets called when monstop command is issued by the user. + It stops the monitoring on all nodes, stops the Nagios daemons. + Arguments: + p_nodes -- a pointer to an arrays of nodes to be stoped for monitoring. null means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means both monservers and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (return code, message) + if the callback is set, use callback to display the status and error. +=cut +#-------------------------------------------------------------------------------- +sub stop { + print "nagiosmon::stop called\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + my $grands=shift; + + #only stop one. this function will get called twice for mn, once for children and once for grand children. + if (($grands) && (keys(%$grands) > 0)) { + return (0, "ok"); + } + + + my $localhostname=hostname(); + + my $rc=`service nagios stop 2>&1`; + reportError("$localhostname: $rc", $callback); + + #go to nodes to start nrpe + if (($scope) && ($noderef)) { + my @mon_nodes=@$noderef; + my %nodes_status=xCAT::Utils->pingNodeStatus(@mon_nodes); + + my $active_nodes=$nodes_status{$::STATUS_ACTIVE}; + if (@$active_nodes > 0) { + my $nodelist=join(',',@$active_nodes); + my $result=`XCATBYPASS=Y $::XCATROOT/bin/xdsh $nodelist "service nrpe stop" 2>&1`; + if ($?) { + reportError("$localhostname: $result", $callback); + return (1, $result); + } + + } + } + + return (0, "stopped"); +} + + +#-------------------------------------------------------------------------------- +=head3 config + This function configures the cluster for the given nodes. + This function is called when moncfg command is issued or when xcatd starts + on the service node. It will configure the cluster to include the given nodes within + the monitoring doamin. + Arguments: + p_nodes -- a pointer to an arrays of nodes to be added for monitoring. none means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + grands -- a hash pointer to store the information of the grandchildren. key: "servicenode,xcatmaseter" for the grandchildren, value: a array pointer of grandchildren nodes. This one is only set when the current node is mn and handleGrandChildren returns 1 by the monitoring plugin. + + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub config { + print "nagiosmon:config called\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + my $grands=shift; + #print "*****nagiosmon::config: noderef:" . Dumper($noderef); + #print "*****nagiosmon::config: grands:" . Dumper($grands); + + my $localhostname=hostname(); + + #the identification of this node + my @hostinfo=xCAT::Utils->determinehostname(); + my $isSN=xCAT::Utils->isServiceNode(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + if (!$isSN) { $iphash{'noservicenode'}=1;} + + #set up the general settings in nagios.cfg file + my $nagios_cfg="/etc/nagios/nagios.cfg"; + if (-f $nagios_cfg) { + #save the old version + if (! -f "$nagios_cfg".".ORIG") { + copy($nagios_cfg, "$nagios_cfg".".ORIG"); + } + copy($nagios_cfg, "$nagios_cfg".".save"); + + if ($isSN) { + #configuration for SN + my @ret=setup_nagios_cfg_sn($nagios_cfg); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret; } + } else { + #configuration for MN + my @ret=setup_nagios_cfg_mn($nagios_cfg); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret; } + } + } else { + return (1, "$nagios_cfg cannot be found. Please make sure Nagios is installed."); + } + + + + #adding children nodes + if (($noderef) && (@$noderef > 0)) { + my $pPairHash=xCAT_monitoring::monitorctrl->getMonServer($noderef); + if (ref($pPairHash) eq 'ARRAY') { + reportError($pPairHash->[1], $callback); + return (0, ""); + } + + #print "noderef=" . Dumper($noderef); + #print "iphash=" . Dumper(%iphash); + #print "pPairHash=" . Dumper($pPairHash); + + foreach my $key (keys (%$pPairHash)) { + my @key_a=split(':', $key); + if (! $iphash{$key_a[0]}) { next;} + my $mon_nodes=$pPairHash->{$key}; + + my $master=$key_a[1]; + + #figure out what nodes to add + my @nodes_to_add=(); + if ($mon_nodes) { + foreach(@$mon_nodes) { + my $node=$_->[0]; + my $nodetype=$_->[1]; + if ($nodetype){ + if ($nodetype =~ /$::NODETYPE_OSI/) { push(@nodes_to_add, $node); } + } + } + } + #print "nodestoadd=@nodes_to_add\n"; + + #add new nodes to the Nagios cluster + if (@nodes_to_add> 0) { + my @ret=addNodes(\@nodes_to_add, $master, $scope, $callback, 0); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret;} + } + } + } + + #for grand childdren + if ((!$isSN) && ($grands) && (keys(%$grands) > 0)) { + my @ret=addGrandNodes($grands, $scope, $callback, 0); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret;} + } + + return (0, "configured"); +} + +sub setup_nagios_cfg_mn { + my $nagios_cfg=shift; + + #set enable_notifications=1 + `grep "enable_notifications=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*enable_notifications=.*\$/enable_notifications=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "enable_notifications=1" >> $nagios_cfg`; + } + + #set execute_service_checks=1 + `grep "execute_service_checks=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*execute_service_checks=.*\$/execute_service_checks=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "execute_service_checks=1" >> $nagios_cfg`; + } + + #set check_external_commands=1 + `grep "check_external_commands=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*check_external_commands=.*\$/check_external_commands=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "check_external_commands=1" >> $nagios_cfg`; + } + + #set accept_passive_service_checks=1 + `grep "accept_passive_service_checks=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*accept_passive_service_checks=.*\$/accept_passive_service_checks=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "accept_passive_service_checks=1" >> $nagios_cfg`; + } + return (0, "ok"); +} + + + + + +sub setup_nagios_cfg_sn { + my $nagios_cfg=shift; + #set enable_notifications=0 + `grep "enable_notifications=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*enable_notifications=.*\$/enable_notifications=0/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "enable_notifications=0" >> $nagios_cfg`; + } + + #set obsess_over_services=1 + `grep "obsess_over_services=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*obsess_over_services=.*\$/obsess_over_services=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "obsess_over_services=1" >> $nagios_cfg`; + } + + #set ocsp_command=submit_service_check_result + `grep "ocsp_command=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*ocsp_command=.*\$/ocsp_command=submit_service_check_result/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "ocsp_command=submit_service_check_result" >> $nagios_cfg`; + } + + #set obsess_over_hosts=1 + `grep "obsess_over_hosts=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*obsess_over_hosts=.*\$/obsess_over_hosts=1/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "obsess_over_hosts=1" >> $nagios_cfg`; + } + + my $local_cfg= "/etc/nagios/objects/localhost.cfg"; + if (-f $local_cfg) { + mv($local_cfg, "$local_cfg.save"); + } + my $rc=`grep "cfg_file=$local_cfg" $nagios_cfg`; + #print "my rc=$rc\n"; + #print "grep \"cfg_file=$local_cfg\" $nagios_cfg\n"; + if ($rc && ($rc !~ /^(\s)*\#/)) { + `sed -i 's/cfg_file=\\\/etc\\\/nagios\\\/objects\\\/localhost.cfg/\#cfg_cfg=\\\/etc\\\/nagios\\\/objects\\\/localhost.cfg/' $nagios_cfg`; + } + + + #set ochp_command=submit_host_check_result + `grep "ochp_command=" $nagios_cfg`; + if ($? == 0) { + my $rc=`sed -i 's/^[\#]*ochp_command=.*\$/ochp_command=submit_host_check_result/' $nagios_cfg`; + if ($?) { + `echo "$rc"`; + } + } else { + `echo "ochp_command=submit_host_check_result" >> $nagios_cfg`; + } + + #add commands in commands.cfg + my $commands_cfg="/etc/nagios/objects/commands.cfg"; + if (-f $commands_cfg) { + #save the old version + if (! -f "$commands_cfg".".ORIG") { + copy($commands_cfg, "$commands_cfg".".ORIG"); + } + copy($commands_cfg, "$commands_cfg".".save"); + + my $rc=`grep "submit_service_check_result" $commands_cfg |grep command_name`; + if (!$rc || ($rc !~ /^(\s)*command_name(\s)+submit_service_check_result$/)) { + `echo "define command{ + command_name submit_service_check_result + command_line /usr/lib/nagios/plugins/eventhandler/submit_service_check_result \\\$HOSTNAME\$ '\\\$SERVICEDESC\\\$' \\\$SERVICESTATE\$ '\\\$SERVICEOUTPUT\\\$' +}" >> $commands_cfg`; + } + my $rc=`grep "submit_host_check_result" $commands_cfg |grep command_name`; + if (!$rc || ($rc !~ /^(\s)*command_name(\s)+submit_host_check_result$/)) { + `echo "define command{ + command_name submit_host_check_result + command_line /usr/lib/nagios/plugins/eventhandler/submit_host_check_result \\\$HOSTNAME\$ \\\$HOSTSTATE\$ '\\\$HOSTOUTPUT\\\$' +}" >> $commands_cfg`; + } + } else { + return (1, "$commands_cfg cannot be found. Please make sure Nagios is installed."); + } + + #create ncsa the commands + my $ocsp_command="/usr/lib/nagios/plugins/eventhandler/submit_service_check_result"; + my $ochp_command="/usr/lib/nagios/plugins/eventhandler/submit_host_check_result"; + my $master=xCAT::Utils->get_site_Master(); + if (!$master) { + my $rc=`grep XCATMASTER /opt/xcat/xcatinfo`; + if ($rc && ($rc =~/^XCATMASTER=(.*)/)) { + $master=$1; + } + } + + my $master_ip="127.0.0.1"; + if ($master) { + $master_ip=xCAT::NetworkUtils::getipaddr($master); + } + #print "master=$master, ip=$master_ip\n"; + + if (-f $ocsp_command) { + #save the old version + if (! -f "$ocsp_command".".ORIG") { + copy($ocsp_command, "$ocsp_command".".ORIG"); + } + copy($ocsp_command, "$ocsp_command".".save"); + } + unlink($ocsp_command); + + if (-f $ochp_command) { + #save the old version + if (! -f "$ochp_command".".ORIG") { + copy($ochp_command, "$ochp_command".".ORIG"); + } + copy($ochp_command, "$ochp_command".".save"); + } + unlink($ochp_command); + + open(FILE1, ">$ocsp_command"); + print FILE1 "\#!/bin/sh +\# Arguments: +\# \$1 = host_name (Short name of host that the service is +\# associated with) +\# \$2 = svc_description (Description of the service) +\# \$3 = state_string (A string representing the status of +\# the given service - \"OK\", \"WARNING\", \"CRITICAL\" +\# or \"UNKNOWN\") +\# \$4 = plugin_output (A text string that should be used +\# as the plugin output for the service checks) +\# + +\# Convert the state string to the corresponding return code +return_code=-1 +case \"\$3\" in + OK) + return_code=0 + ;; + WARNING) + return_code=1 + ;; + CRITICAL) + return_code=2 + ;; + UNKNOWN) + return_code=-1 + ;; +esac + +echo \"1=\$1, 2=\$2, 3=\$3, 4=\$4, return_code=\$return_code\" >> /tmp/6.txt +\# pipe the service check info into the send_nsca program, which +\# in turn transmits the data to the nsca daemon on the central +\# monitoring server +/usr/bin/printf \"%s\\t%s\\t%s\\t%s\\n\" \"\$1\" \"\$2\" \"\$return_code\" \"\$4\" | /usr/bin/send_nsca -H $master_ip -c /etc/nagios/send_nsca.cfg +"; + close FILE1; + + open(FILE2, ">$ochp_command"); + print FILE2 "\#!/bin/sh +\# Arguments: +\# \$1 = host_name (Short name of host that the service is +\# associated with) +\# \$2 = state_string (A string representing the status of +\# the given host - \"UP\", \"DOWN\") +\# \$3 = plugin_output (A text string that should be used +\# as the plugin output for the host checks) +\# + +# Convert the state string to the corresponding return code +return_code=-1 +case \"\$2\" in + UP) + return_code=0 + ;; + DOWN) + return_code=1 + ;; + UNREACHABLE) + return_code=1 + ;; + UNKNOWN) + return_code=-1 + ;; +esac +echo \"1=\$1, 2=\$2, 3=\$3, return_code=\$return_code\" >> /tmp/5.txt + +\# pipe the service check info into the send_nsca program, which +\# in turn transmits the data to the nsca daemon on the central +\# monitoring server +/usr/bin/printf \"%s\\t%s\\t%s\\n\" \"\$1\" \"\$return_code\" \"\$3\" | /usr/bin/send_nsca -H $master_ip -c /etc/nagios/send_nsca.cfg +"; + close FILE2; + + chmod 0755, "$ocsp_command", "$ochp_command"; + return (0, "ok"); +} + +#-------------------------------------------------------------------------------- +=head3 addNodes + This function adds the nodes into the nagios cluster. + Arguments: + nodes --an array of nodes to be added. + master -- the monitoring master of the node. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub addNodes { + my $pmon_nodes=shift; + if ($pmon_nodes =~ /xCAT_monitoring::nagiosmon/) { + $pmon_nodes=shift; + } + + my @mon_nodes = @$pmon_nodes; + if (@mon_nodes==0) { return (0, "");} + + my $master=shift; + my $scope=shift; + my $callback=shift; + print "nagiosmon.addNodes mon_nodes=@mon_nodes\n"; + + my @hostinfo=xCAT::Utils->determinehostname(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + my $localhostname=hostname(); + + + my $mychildren_cfg="/etc/nagios/objects/mychildren.cfg"; + my $nagios_cfg="/etc/nagios/nagios.cfg"; + + if (-f $mychildren_cfg) { + #save the old version + if (! -f "$mychildren_cfg".".ORIG") { + copy($mychildren_cfg, "$mychildren_cfg".".ORIG"); + } + copy($mychildren_cfg, "$mychildren_cfg".".save"); + } + + #populate mychildren with new hosts + #print "defining hosts in $mychildren_cfg\n"; + foreach my $node (@mon_nodes) { + my $rc=`grep host_name $mychildren_cfg |grep $node`; + if (($rc) && ($rc =~ /host_name(\s)+$node(\s)*$/)) { + #if found, remove first + `sed -i "/#BEGIN HOST $node/,/#END HOST $node/ d" $mychildren_cfg` + } + my $ip=xCAT::NetworkUtils->getipaddr($node); + #print "ip=$ip\n"; + `echo "\#BEGIN HOST $node +define host\{ + use linux-server + host_name $node + alias $node + address $ip + max_check_attempts 10 + contact_groups admins +\} +\#END HOST $node" >> $mychildren_cfg`; + } + + #define host group for the nodes + #print "defining host_group in $mychildren_cfg\n"; + my $rc=`grep "hostgroup_name" $mychildren_cfg`; + if (!$rc || ($rc !~ /^(\s)*hostgroup_name(\s)+mychildren/)) { + `echo "define hostgroup{ + hostgroup_name mychildren + alias mychildren + members +} +" >> $mychildren_cfg`; + } + $rc=`grep "members" $mychildren_cfg`; + if ($rc && ($rc =~ /members(\s)+(.*)/)) { + my $oldnodes=$2; + my %nodehash=(); + if ($oldnodes) { + my @a=split(',', $oldnodes); + + foreach (@a) { + $nodehash{$_}=1; + } + } + foreach my $node (@mon_nodes) { + if (!exists($nodehash{$node})) { + $nodehash{$node}=1; + } + } + my $newnodes=join(',', keys(%nodehash)); + if ($newnodes) { + `sed -i 's/members.*\$/members $newnodes/' $mychildren_cfg`; + } + } + + #add nrpe command in mychildren.cfg file + #print "defining nrpe command in $mychildren_cfg\n"; + my $rc=`grep "command_name" $mychildren_cfg`; + if (!$rc || ($rc !~ /^(\s)*command_name(\s)+check_nrpe/)) { + `echo "\#check_nrpe command definition +define command{ +command_name check_nrpe +command_line \\\$USER1\$/check_nrpe -H \\\$HOSTADDRESS\$ -t 30 -c \\\$ARG1\$ +} +" >> $mychildren_cfg`; + } + + #define services for the new hosts + #print "defining services in $mychildren_cfg\n"; + my $rc=`grep "service_description" $mychildren_cfg`; + if (!$rc || ($rc !~ /(\s)*service_description(\s)+SSH/)) { + `echo "define service{ + use generic-service + hostgroups mychildren + service_description SSH + check_command check_ssh +} +" >> $mychildren_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+FTP/)) { + `echo "define service{ + use generic-service + hostgroups mychildren + service_description FTP + check_command check_ftp +} +" >> $mychildren_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+Load(\s)*/)) { + `echo "define service{ + use generic-service + contact_groups admins + hostgroups mychildren + service_description Load + check_command check_nrpe!check_load +} +" >> $mychildren_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+Processes(\s)*/)) { + `echo "define service{ + use generic-service + contact_groups admins + hostgroups mychildren + service_description Processes + check_command check_nrpe!check_total_procs +} +" >> $mychildren_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+Users(\s)*/)) { + `echo "define service{ + use generic-service + contact_groups admins + hostgroups mychildren + service_description Users + check_command check_nrpe!check_users +} +" >> $mychildren_cfg`; + } + + #add cfg_file=/etc/nagios/objects/mychildren.cfg to nagios.cfg file + #print "adding $mychildren_cfg to $nagios_cfg file.\n"; + my $rc=`grep "mychildren.cfg" $nagios_cfg`; + if (!$rc || ($rc !~ /^cfg_file=(.*)\/mychildren.cfg/)) { + `echo "\#BEGIN xCAT configiration file mychildren +cfg_file=/etc/nagios/objects/mychildren.cfg +\#END xCAT configiration file mychildren +" >> $nagios_cfg`; + } + + + #go to nodes to configure nrpe + my $inactive_nodes=[]; + if ($scope) { + #print "Configuring the nodes.\n"; + my %nodes_status=xCAT::Utils->pingNodeStatus(@mon_nodes); + $inactive_nodes=$nodes_status{$::STATUS_INACTIVE}; + if (@$inactive_nodes>0) { + my $error="The following nodes cannot be configured because they are inactive:\n @$inactive_nodes."; + reportError($error, $callback); + } + + my $active_nodes=$nodes_status{$::STATUS_ACTIVE}; + if (@$active_nodes > 0) { + my $nodelist=join(',',@$active_nodes); + my $result=`XCATBYPASS=Y $::XCATROOT/bin/updatenode $nodelist -P confNagios 2>&1`; + if ($?) { + my $error= "$result"; + reportError($error, $callback); + return (1, $error); + } + } + } + + return (0, "ok"); +} + + +#-------------------------------------------------------------------------------- +=head3 removeNodes + This function removes the nodes from the nagios cluster. + Arguments: + nodes --an array of nodes to be removed. + master -- the monitoring master of the node. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub removeNodes { + my $pmon_nodes=shift; + if ($pmon_nodes =~ /xCAT_monitoring::nagiosmon/) { + $pmon_nodes=shift; + } + + my @mon_nodes = @$pmon_nodes; + if (@mon_nodes==0) { return (0, "");} + + my $master=shift; + my $scope=shift; + my $callback=shift; + print "nagiosmon.removeNodes mon_nodes=@mon_nodes\n"; + + my @hostinfo=xCAT::Utils->determinehostname(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + my $localhostname=hostname(); + + + my $mychildren_cfg="/etc/nagios/objects/mychildren.cfg"; + my $nagios_cfg="/etc/nagios/nagios.cfg"; + + if (-f $mychildren_cfg) { + #save the old version + if (! -f "$mychildren_cfg".".ORIG") { + copy($mychildren_cfg, "$mychildren_cfg".".ORIG"); + } + copy($mychildren_cfg, "$mychildren_cfg".".save"); + } + + if (-f $mychildren_cfg) { + + #remove from the host group + my $rc=`grep "hostgroup_name" $mychildren_cfg`; + if ($rc && ($rc =~ /^(\s)*hostgroup_name(\s)+mychildren/)) { + $rc=`grep "members" $mychildren_cfg`; + if ($rc && ($rc =~ /members(\s)+(.*)/)) { + my $oldnodes=$2; + my %nodehash=(); + if ($oldnodes) { + my @a=split(',', $oldnodes); + + foreach (@a) { + $nodehash{$_}=1; + } + } + foreach my $node (@mon_nodes) { + if (exists($nodehash{$node})) { + delete($nodehash{$node}); + } + } + my $newnodes=join(',', keys(%nodehash)); + if ($newnodes) { + `sed -i 's/members.*\$/members $newnodes/' $mychildren_cfg`; + + #remove the given hosts from mychildren.cfg + foreach my $node (@mon_nodes) { + my $rc=`grep host_name $mychildren_cfg |grep $node`; + if (($rc) && ($rc =~ /host_name(\s)+$node(\s)*$/)) { + #if found, remove it + `sed -i "/#BEGIN HOST $node/,/#END HOST $node/ d" $mychildren_cfg` + } + } + } else { #no nodes in mychildren.cfg + #remove the file and remove it from nagios.cfg + unlink($mychildren_cfg); + my $rc=`grep "mychildren.cfg" $nagios_cfg`; + if ($rc && ($rc =~ /^cfg_file=(.*)\/mychildren.cfg/)) { + `sed -i "/#BEGIN xCAT configiration file mychildren/,/#END xCAT configiration file mychildren/ d" $nagios_cfg`; + } + } + } + } + + } + + return (0, "ok"); +} + + +#-------------------------------------------------------------------------------- +=head3 addGrandNodes + This function adds the grand children nodes into the nagios cluster. + Arguments: + grands -- pointer to a hash. key: "servicenode, xcatmaster" for the nodes, + value: an array pointer to the nodes. + master -- the monitoring master of the node. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub addGrandNodes { + my $grands=shift; + if ($grands =~ /xCAT_monitoring::nagiosmon/) { + $grands=shift; + } + + my $scope=shift; + my $callback=shift; + print "nagiosmon.addGrandNodes\n"; + + my @hostinfo=xCAT::Utils->determinehostname(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + my $localhostname=hostname(); + + + my $cn_template_cfg="/etc/nagios/objects/cn_template.cfg"; + my $nagios_cfg="/etc/nagios/nagios.cfg"; + + #create cn_template.cfg + if (-f $cn_template_cfg) { + #save the old version + if (! -f "$cn_template_cfg".".ORIG") { + copy($cn_template_cfg, "$cn_template_cfg".".ORIG"); + } + copy($cn_template_cfg, "$cn_template_cfg".".save"); + } + #print "defining xCAT-node in $cn_template_cfg\n"; + my $rc=`grep "xCAT-node" $cn_template_cfg`; + if (!$rc || ($rc !~ /^(\s)*name(\s)+xCAT-node/)) { + `echo "define host{ + name xCAT-node + use generic-host + check_period 24x7 + active_checks_enabled 0 + passive_checks_enabled 1 + check_interval 5 + retry_interval 1 + max_check_attempts 10 + check_command check-host-alive + notification_period workhours + notification_interval 120 + notification_options d,u,r + contact_groups admins + register 0 + } +" >> $cn_template_cfg`; + + } + + + foreach my $sv_pair (keys(%$grands)) { + my @server_pair=split(',', $sv_pair); + my $sv=$server_pair[0]; + my $sv1; + if (@server_pair>1) { + $sv1=$server_pair[1]; + } + my $pnodes=$grands->{$sv_pair}; + my @mon_nodes; + if ($pnodes) { + @mon_nodes=@$pnodes; + } + + my $cn_cfg="/etc/nagios/objects/cn_$sv.cfg"; + + #create compute node cfg file for a service node + if (-f $cn_cfg) { + copy($cn_cfg, "$cn_cfg".".save"); + } + + + #populate cn cfg with new hosts + #print "defining hosts in $cn_cfg\n"; + foreach my $node (@mon_nodes) { + my $rc=`grep host_name $cn_cfg |grep $node`; + if (($rc) && ($rc =~ /host_name(\s)+$node(\s)*$/)) { + #if found, remove first + `sed -i "/#BEGIN HOST $node/,/#END HOST $node/ d" $cn_cfg` + } + my $ip=xCAT::NetworkUtils->getipaddr($node); + #print "ip=$ip\n"; + `echo "\#BEGIN HOST $node +define host\{ + use xCAT-node + host_name $node + alias $node + address $ip + parents $sv +\} +\#END HOST $node" >> $cn_cfg`; + } + + #define host group for the nodes + #print "defining host_group in $cn_cfg\n"; + my $rc=`grep "hostgroup_name" $cn_cfg`; + if (!$rc || ($rc !~ /^(\s)*hostgroup_name(\s)+cn_$sv/)) { + `echo "define hostgroup{ + hostgroup_name cn_$sv + alias cn_$sv + members +} +" >> $cn_cfg`; + } + $rc=`grep "members" $cn_cfg`; + if ($rc && ($rc =~ /members(\s)+(.*)/)) { + my $oldnodes=$2; + my %nodehash=(); + if ($oldnodes) { + my @a=split(',', $oldnodes); + + foreach (@a) { + $nodehash{$_}=1; + } + } + foreach my $node (@mon_nodes) { + if (!exists($nodehash{$node})) { + $nodehash{$node}=1; + } + } + my $newnodes=join(',', keys(%nodehash)); + if ($newnodes) { + `sed -i 's/members.*\$/members $newnodes/' $cn_cfg`; + } + } + + + #define services for the new hosts + #print "defining services in $cn_cfg\n"; + my $rc=`grep "service_description" $cn_cfg`; + if (!$rc || ($rc !~ /(\s)*service_description(\s)+SSH/)) { + `echo "define service{ + use generic-service + hostgroups cn_$sv + service_description SSH + check_command check_ssh + active_checks_enabled 0 + passive_checks_enabled 1 +} +" >> $cn_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+FTP/)) { + `echo "define service{ + use generic-service + hostgroups cn_$sv + service_description FTP + check_command check_ssh + active_checks_enabled 0 + passive_checks_enabled 1 +} +" >> $cn_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+Load(\s)*/)) { + `echo "define service{ + use generic-service + hostgroups cn_$sv + service_description Load + check_command check_ssh + active_checks_enabled 0 + passive_checks_enabled 1 +} +" >> $cn_cfg`; + } + if (!$rc || ($rc !~ /(\s)*service_description(\s)+Processes(\s)*/)) { + `echo "define service{ + use generic-service + hostgroups cn_$sv + service_description Processes + check_command check_ssh + active_checks_enabled 0 + passive_checks_enabled 1 +} +" >> $cn_cfg`; + } + + #add cfg_file=/etc/nagios/objects/cn_$sv.cfg to nagios.cfg file + #print "adding $cn_cfg to $nagios_cfg file.\n"; + my $rc=`grep "cn_$sv.cfg" $nagios_cfg`; + if (!$rc || ($rc !~ /^cfg_file=(.*)\/cn_$sv.cfg/)) { + `echo "\#BEGIN xCAT configiration file cn_$sv +cfg_file=/etc/nagios/objects/cn_$sv.cfg +\#END xCAT configiration file cn_$sv +" >> $nagios_cfg`; + } + #print "adding $cn_template_cfg to $nagios_cfg file.\n"; + my $rc=`grep "cn_template.cfg" $nagios_cfg`; + if (!$rc || ($rc !~ /^cfg_file=(.*)\/cn_template.cfg/)) { + `echo "\#BEGIN xCAT configiration file for grandchildren template +cfg_file=$cn_template_cfg +\#END xCAT configiration file for grandchildren template +" >> $nagios_cfg`; + } + } + + return (0, "ok"); +} + + + + + +#-------------------------------------------------------------------------------- +=head3 removeGrandNodes + This function removes the grand children nodes from the nagios cluster. + Arguments: + grands -- pointer to a hash. key: "servicenode, xcatmaster" for the nodes, + value: an array pointer to the nodes. + master -- the monitoring master of the node. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub removeGrandNodes { + my $grands=shift; + if ($grands =~ /xCAT_monitoring::nagiosmon/) { + $grands=shift; + } + + my $scope=shift; + my $callback=shift; + print "nagiosmon.removeGrandNodes\n"; + + my @hostinfo=xCAT::Utils->determinehostname(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + my $localhostname=hostname(); + my $nagios_cfg="/etc/nagios/nagios.cfg"; + + + foreach my $sv_pair (keys(%$grands)) { + my @server_pair=split(',', $sv_pair); + my $sv=$server_pair[0]; + my $sv1; + if (@server_pair>1) { + $sv1=$server_pair[1]; + } + my $pnodes=$grands->{$sv_pair}; + my @mon_nodes; + if ($pnodes) { + @mon_nodes=@$pnodes; + } + + my $cn_cfg="/etc/nagios/objects/cn_$sv.cfg"; + if (-f $cn_cfg) { + #remove hosts from the hostgroup + my $rc=`grep "hostgroup_name" $cn_cfg`; + if ($rc && ($rc =~ /^(\s)*hostgroup_name(\s)+cn_$sv/)) { + + $rc=`grep "members" $cn_cfg`; + if ($rc && ($rc =~ /members(\s)+(.*)/)) { + my $oldnodes=$2; + my %nodehash=(); + if ($oldnodes) { + my @a=split(',', $oldnodes); + + foreach (@a) { + $nodehash{$_}=1; + } + } + foreach my $node (@mon_nodes) { + if (exists($nodehash{$node})) { + delete($nodehash{$node}); + } + } + my $newnodes=join(',', keys(%nodehash)); + if ($newnodes) { + `sed -i 's/members.*\$/members $newnodes/' $cn_cfg`; + #remove the hosts from cn cfg + foreach my $node (@mon_nodes) { + my $rc=`grep host_name $cn_cfg |grep $node`; + if (($rc) && ($rc =~ /host_name(\s)+$node(\s)*$/)) { + #if found, remove it + `sed -i "/#BEGIN HOST $node/,/#END HOST $node/ d" $cn_cfg` + } + } + } else { + unlink($cn_cfg); + my $rc=`grep "$cn_cfg" $nagios_cfg`; + if ($rc || ($rc =~ /^cfg_file=(.*)\/cn_$sv.cfg/)) { + `sed -i "/#BEGIN xCAT configiration file cn_$sv/,/#END xCAT configiration file cn_$sv/ d" $nagios_cfg`; + } + } + + } + } + } + } + + return (0, "ok"); +} + + + +#-------------------------------------------------------------------------------- +=head3 deconfig + This function de-configures the cluster for the given nodes. + This function is called when mondecfg command is issued by the user. + It should remove the given nodes from the product for monitoring. + Arguments: + p_nodes -- a pointer to an arrays of nodes to be removed for monitoring. none means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means local host only. + 2 means both local host and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub deconfig { + print "nagiosmon:deconfig called\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + my $grands=shift; + my $localhostname=hostname(); + + #the identification of this node + my @hostinfo=xCAT::Utils->determinehostname(); + my $isSN=xCAT::Utils->isServiceNode(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + if (!$isSN) { $iphash{'noservicenode'}=1;} + + + #removinging children nodes + if (($noderef) && (@$noderef > 0)) { + my $pPairHash=xCAT_monitoring::monitorctrl->getMonServer($noderef); + if (ref($pPairHash) eq 'ARRAY') { + reportError($pPairHash->[1], $callback); + return (0, ""); + } + + #print "noderef=" . Dumper($noderef); + #print "iphash=" . Dumper(%iphash); + #print "pPairHash=" . Dumper($pPairHash); + + foreach my $key (keys (%$pPairHash)) { + my @key_a=split(':', $key); + if (! $iphash{$key_a[0]}) { next;} + my $mon_nodes=$pPairHash->{$key}; + + my $master=$key_a[1]; + + #figure out what nodes to remove + my @nodes_to_rm=(); + if ($mon_nodes) { + foreach(@$mon_nodes) { + my $node=$_->[0]; + my $nodetype=$_->[1]; + if ($nodetype){ + if ($nodetype =~ /$::NODETYPE_OSI/) { push(@nodes_to_rm, $node); } + } + } + } + #print "nodes to rme=@nodes_to_rm\n"; + + #remove new nodes to the Nagios cluster + if (@nodes_to_rm> 0) { + my @ret=removeNodes(\@nodes_to_rm, $master, $scope, $callback, 0); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret;} + } + } + } + + + #for grand childdren + if ((!$isSN) && ($grands) && (keys(%$grands) > 0)) { + my @ret=removeGrandNodes($grands, $scope, $callback, 0); + if ((@ret > 0) && ($ret[0] != 0)) { return @ret;} + } + + return (0, "deconfigured"); +} + +#-------------------------------------------------------------------------------- +=head3 supportNodeStatusMon + This function is called by the monitorctrl module to check + if Nagios can help monitoring and returning the node status. + + Arguments: + none + Returns: + 1 +=cut +#-------------------------------------------------------------------------------- +sub supportNodeStatusMon { + print "nagiosmon::supportNodeStatusMon called\n"; + return 0; +} + + + +#-------------------------------------------------------------------------------- +=head3 startNodeStatusMon + This function is called by the monitorctrl module to tell + Nagios to start monitoring the node status and feed them back + to xCAT. Nagios will start setting up the notification + to monitor the node status changes. + + Arguments: + p_nodes -- a pointer to an arrays of nodes for monitoring. none means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means local host only. + 2 means both local host and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub startNodeStatusMon { + print "nagiosmon::startNodeStatusMon\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + + my $localhostname=hostname(); + my $retcode=0; + my $retmsg=""; + + + my $isSN=xCAT::Utils->isServiceNode(); + + #get all the nodes status from IBM.MngNode class of local host and + #the identification of this node + my $pPairHash=xCAT_monitoring::monitorctrl->getMonServer($noderef); + if (ref($pPairHash) eq 'ARRAY') { + reportError($pPairHash->[1], $callback); + return (1, ""); + } + + my @hostinfo=xCAT::Utils->determinehostname(); + my %iphash=(); + foreach(@hostinfo) {$iphash{$_}=1;} + if (!$isSN) { $iphash{'noservicenode'}=1;} + + + return ($retcode, $retmsg); +} + + + + +#-------------------------------------------------------------------------------- +=head3 stopNodeStatusMon + This function is called by the monitorctrl module to tell + Nagios to stop feeding the node status info back to xCAT. It will + stop the notification that is monitoring the node status. + + Arguments: + p_nodes -- a pointer to an arrays of nodes for monitoring. none means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means local host only. + 2 means both local host and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (return code, message) +=cut +#-------------------------------------------------------------------------------- +sub stopNodeStatusMon { + print "nagiosmon::stopNodeStatusMon called\n"; + my $noderef=shift; + if ($noderef =~ /xCAT_monitoring::nagiosmon/) { + $noderef=shift; + } + my $scope=shift; + my $callback=shift; + + my $retcode=0; + my $retmsg=""; + + my $isSN=xCAT::Utils->isServiceNode(); + my $localhostname=hostname(); + + + return ($retcode, $retmsg); +} + + + +#-------------------------------------------------------------------------------- +=head3 reportError + This function writes the error message to the callback, otherwise to syslog. + Arguments: + error + callback + Returns: + none +=cut +#-------------------------------------------------------------------------------- +sub reportError +{ + my $error=shift; + my $callback=shift; + if ($callback) { + my $rsp={}; + $rsp->{data}->[0]=$error; + $callback->($rsp); + } else { xCAT::MsgUtils->message('S', "[mon]: $error\n"); } + return; +} + + +#-------------------------------------------------------------------------------- +=head3 processSettingChanges + This function gets called when the setting for this monitoring plugin + has been changed in the monsetting table. + Arguments: + none. + Returns: + 0 for successful. + non-0 for not successful. +=cut +#-------------------------------------------------------------------------------- +sub processSettingChanges { +} + +#-------------------------------------------------------------------------------- +=head3 getDiscription + This function returns the detailed description of the plugin inluding the + valid values for its settings in the monsetting tabel. + Arguments: + none + Returns: + The description. +=cut +#-------------------------------------------------------------------------------- +sub getDescription { + return +" Description: + nagiosmon is a monitoring plug-in for Nagios to monitor xCAT cluster. It defines hosts, host groups and services in the Nagios configuration files. The xCAT nodes and services will to be monitored by Nagios with its NRPE and NSCA add-ons. The following sequence of commands will do the configuration and monitoring. + monadd nagiosmon + moncfg nagiosmon service -r + moncfg nagiosmon compute -r + monstart nagiosmon service -r + monstart nagiosmon compute -r + where 'service' is the node group name for the service node, 'compute' is the node group name for the compute node. +"; + +} + + +#-------------------------------------------------------------------------------- +=head3 getPostscripts + This function returns the postscripts needed for the nodes and for the servicd + nodes. + Arguments: + none + Returns: + The the postscripts. It a pointer to an array with the node group names as the keys + and the comma separated poscript names as the value. For example: + {service=>"cmd1,cmd2", xcatdefaults=>"cmd3,cmd4"} where xcatdefults is a group + of all nodes including the service nodes. +=cut +#-------------------------------------------------------------------------------- +sub getPostscripts { + my $ret={}; + $ret->{xcatdefaults}="confNagios"; + return $ret; +} + + + +#-------------------------------------------------------------------------------- +=head3 show + This function shows the monitoring status. + This function is called when monshow command is issued. + Arguments: + p_nodes -- a pointer to an arrays of nodes to be added for monitoring. none means all. + scope -- the action scope, it indicates the node type the action will take place. + 0 means localhost only. + 2 means localhost and nodes, + callback -- the callback pointer for error and status displaying. It can be null. + Returns: + (error code, error message) +=cut +#-------------------------------------------------------------------------------- +sub show +{ + print "nagiosmon:show called\n"; + no strict 'refs'; + my ($noderef, $sum, $time, $attrs, $pe, $where,$callback) = @_; + + return (0, ""); +} + + +#-------------------------------------------------------------------------- +=head3 handleGrandChildren + This function tells if the mn shall handle the nodes that are managed by the service nodes. + +=cut +#--------------------------------------------------------------------------- +sub handleGrandChildren { + return 1; +} + diff --git a/xCAT-server/lib/xcat/plugins/monctrlcmds.pm b/xCAT-server/lib/xcat/plugins/monctrlcmds.pm index a3658b2b0..889ce9684 100644 --- a/xCAT-server/lib/xcat/plugins/monctrlcmds.pm +++ b/xCAT-server/lib/xcat/plugins/monctrlcmds.pm @@ -13,6 +13,8 @@ use xCAT::MsgUtils; use xCAT_monitoring::monitorctrl; use xCAT::Utils; use Sys::Hostname; +use Data::Dumper; + 1; @@ -90,7 +92,7 @@ sub preprocess_request return; } else { my $allnodes=$a_ret[4]; - print "allnodes=@$allnodes\n"; + #print "allnodes=@$allnodes\n"; my $pname=$a_ret[1]; my $file_name="$::XCATROOT/lib/perl/xCAT_monitoring/$pname.pm"; my $module_name="xCAT_monitoring::$pname"; @@ -115,6 +117,8 @@ sub preprocess_request $mon_hierachy=xCAT_monitoring::monitorctrl->getNodeMonServerPair($allnodes, 1); } + #print Dumper($mon_hierachy); + if (ref($mon_hierachy) eq 'ARRAY') { my $rsp2={}; $rsp2->{data}->[0]=$mon_hierachy->[1]; @@ -132,39 +136,77 @@ sub preprocess_request foreach(@hostinfo) {$iphash{$_}=1;} if (!$isSV) { $iphash{'noservicenode'}=1;} - foreach (@mon_servers) { + #check if we should also pass nodes that are managed by the sn to mn. + my $handleGrands=0; + if (!$isSV) { + if (defined(${$module_name."::"}{handleGrandChildren})) { + $handleGrands=${$module_name."::"}{handleGrandChildren}->(); + } + } + #print "handleGrands=$handleGrands\n"; + + my $index=0; + my $reqcopy_grands = {%$req}; + foreach my $sv_pair (@mon_servers) { #service node come in pairs, the first one is the monserver adapter that facing the mn, # the second one is facing the cn. we use the first one here - my @server_pair=split(':', $_); + my @server_pair=split(':', $sv_pair); my $sv=$server_pair[0]; - my $mon_nodes=$mon_hierachy->{$_}; + my $sv1; + if (@server_pair>1) { + $sv1=$server_pair[1]; + } + my $mon_nodes=$mon_hierachy->{$sv_pair}; if ((!$mon_nodes) || (@$mon_nodes ==0)) { next; } - print "sv=$sv, nodes=@$mon_nodes\n"; + #print "sv=$sv, nodes=@$mon_nodes\n"; my $reqcopy = {%$req}; if (! $iphash{$sv}) { - if ($isSV) { next; } #if the command is issued on the monserver, only handle its children. - $reqcopy->{'_xcatdest'}=$sv; - $reqcopy->{_xcatpreprocessed}->[0] = 1; - my $rsp2={}; - $rsp2->{data}->[0]="sending request to $sv..., ".join(',', @$mon_nodes); - $callback->($rsp2); - } - - push @{$reqcopy->{module}}, $a_ret[1]; + if ($isSV) { next; } #if the command is issued on the monserver, only handle its children. + else { + if ($handleGrands) { + $index++; + $reqcopy_grands->{"grand_$index"}="$sv,$sv1," . join(',', @$mon_nodes); + } + } + $reqcopy->{'_xcatdest'}=$sv; + $reqcopy->{_xcatpreprocessed}->[0] = 1; + my $rsp2={}; + $rsp2->{data}->[0]="sending request to $sv..., ".join(',', @$mon_nodes); + $callback->($rsp2); + } + + push @{$reqcopy->{module}}, $a_ret[1]; if($command eq "monshow"){ - push @{$reqcopy->{priv}}, $a_ret[2]; - push @{$reqcopy->{priv}}, $a_ret[3]; - push @{$reqcopy->{priv}}, $a_ret[5]; - push @{$reqcopy->{priv}}, $a_ret[6]; - push @{$reqcopy->{priv}}, $a_ret[7]; + push @{$reqcopy->{priv}}, $a_ret[2]; + push @{$reqcopy->{priv}}, $a_ret[3]; + push @{$reqcopy->{priv}}, $a_ret[5]; + push @{$reqcopy->{priv}}, $a_ret[6]; + push @{$reqcopy->{priv}}, $a_ret[7]; } else { - push @{$reqcopy->{nodestatmon}}, $a_ret[2]; - push @{$reqcopy->{scope}}, $a_ret[3]; + push @{$reqcopy->{nodestatmon}}, $a_ret[2]; + push @{$reqcopy->{scope}}, $a_ret[3]; } - push @{$reqcopy->{nodeinfo}}, join(',', @$mon_nodes); - push @requests, $reqcopy; - } + push @{$reqcopy->{nodeinfo}}, join(',', @$mon_nodes); + push @requests, $reqcopy; + } + + #add the a request for mn to handle all its grand children + if ($index > 0) { + $reqcopy_grands->{grand_total}=$index; + push @{$reqcopy_grands->{module}}, $a_ret[1]; + if($command eq "monshow"){ + push @{$reqcopy_grands->{priv}}, $a_ret[2]; + push @{$reqcopy_grands->{priv}}, $a_ret[3]; + push @{$reqcopy_grands->{priv}}, $a_ret[5]; + push @{$reqcopy_grands->{priv}}, $a_ret[6]; + push @{$reqcopy_grands->{priv}}, $a_ret[7]; + } else { + push @{$reqcopy_grands->{nodestatmon}}, $a_ret[2]; + push @{$reqcopy_grands->{scope}}, $a_ret[3]; + } + push @requests, $reqcopy_grands; + } } } else { my $reqcopy = {%$req}; @@ -411,13 +453,32 @@ sub monstart { my $scope=$request->{scope}->[0]; my $nodeinfo=$request->{nodeinfo}->[0]; - my @nodes=split(',', $nodeinfo); - print "monstart get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=$nodeinfo\nscope=$scope\n"; + my $grands={}; + my $total=0; + if (exists($request->{grand_total})) { + $total=$request->{grand_total}; + } + for (my $i=1; $i<= $total; $i++) { + if (exists($request->{"grand_$i"})) { + my $temp=$request->{"grand_$i"}; + my @tmpnodes=split(',', $temp); + if (@tmpnodes > 2) { + my $sv=shift(@tmpnodes); + my $sv1=shift(@tmpnodes); + $grands->{"$sv,$sv1"}=\@tmpnodes; + } + } + } + #print "-------grands" . Dumper($grands); - xCAT_monitoring::monitorctrl->startMonitoring([$pname], \@nodes, $scope, $callback); + + my @nodes=split(',', $nodeinfo); + #print "monstart get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=$nodeinfo\nscope=$scope\n"; + + xCAT_monitoring::monitorctrl->startMonitoring([$pname], \@nodes, $scope, $callback, $grands); if ($nodestatmon) { - xCAT_monitoring::monitorctrl->startNodeStatusMonitoring($pname, \@nodes, $scope, $callback); + xCAT_monitoring::monitorctrl->startNodeStatusMonitoring($pname, \@nodes, $scope, $callback, $grands); } return; } @@ -596,14 +657,34 @@ sub monstop { my $scope=$request->{scope}->[0]; my $nodeinfo=$request->{nodeinfo}->[0]; + + my $grands={}; + my $total=0; + if (exists($request->{grand_total})) { + $total=$request->{grand_total}; + } + for (my $i=1; $i<= $total; $i++) { + if (exists($request->{"grand_$i"})) { + my $temp=$request->{"grand_$i"}; + my @tmpnodes=split(',', $temp); + if (@tmpnodes > 2) { + my $sv=shift(@tmpnodes); + my $sv1=shift(@tmpnodes); + $grands->{"$sv,$sv1"}=\@tmpnodes; + } + } + } + #print "-------grands" . Dumper($grands); + + my @nodes=split(',', $nodeinfo); - print "monstop get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; + #print "monstop get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; if ($nodestatmon) { - xCAT_monitoring::monitorctrl->stopNodeStatusMonitoring($pname, \@nodes, $scope, $callback); + xCAT_monitoring::monitorctrl->stopNodeStatusMonitoring($pname, \@nodes, $scope, $callback, $grands); } - xCAT_monitoring::monitorctrl->stopMonitoring([$pname], \@nodes, $scope, $callback); + xCAT_monitoring::monitorctrl->stopMonitoring([$pname], \@nodes, $scope, $callback, $grands); return; } @@ -1003,7 +1084,7 @@ sub monadd { foreach my $group (@pn) { my $posts=$postscripts_h->{$group}; if ($posts) { - (my $ref) = $table2->getAttribs({node => $group}, 'postscripts'); + (my $ref) = $table2->getAttribs({node => $group}, 'postscripts'); if ($ref and $ref->{postscripts}) { my @old_a=split(',', $ref->{postscripts}); my @new_a=split(',', $posts); @@ -1399,10 +1480,30 @@ sub moncfg my $scope=$request->{scope}->[0]; my $nodeinfo=$request->{nodeinfo}->[0]; - my @nodes=split(',', $nodeinfo); - print "moncfg get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; + #print "---------monctrlcmnd::moncfg request=" . Dumper($request); + + my $grands={}; + my $total=0; + if (exists($request->{grand_total})) { + $total=$request->{grand_total}; + } + for (my $i=1; $i<= $total; $i++) { + if (exists($request->{"grand_$i"})) { + my $temp=$request->{"grand_$i"}; + my @tmpnodes=split(',', $temp); + if (@tmpnodes > 2) { + my $sv=shift(@tmpnodes); + my $sv1=shift(@tmpnodes); + $grands->{"$sv,$sv1"}=\@tmpnodes; + } + } + } + #print "-------grands" . Dumper($grands); - xCAT_monitoring::monitorctrl->config([$pname], \@nodes, $scope, $callback); + my @nodes=split(',', $nodeinfo); + #print "moncfg get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; + + xCAT_monitoring::monitorctrl->config([$pname], \@nodes, $scope, $callback, $grands); return 0; } @@ -1583,10 +1684,29 @@ sub mondecfg my $scope=$request->{scope}->[0]; my $nodeinfo=$request->{nodeinfo}->[0]; - my @nodes=split(',', $nodeinfo); - print "mondecfg get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; + my $grands={}; + my $total=0; + if (exists($request->{grand_total})) { + $total=$request->{grand_total}; + } + for (my $i=1; $i<= $total; $i++) { + if (exists($request->{"grand_$i"})) { + my $temp=$request->{"grand_$i"}; + my @tmpnodes=split(',', $temp); + if (@tmpnodes > 2) { + my $sv=shift(@tmpnodes); + my $sv1=shift(@tmpnodes); + $grands->{"$sv,$sv1"}=\@tmpnodes; + } + } + } + #print "-------grands" . Dumper($grands); + + my @nodes=split(',', $nodeinfo); + #print "mondecfg get called: pname=$pname\nnodestatmon=$nodestatmon\nnodeinfo=@nodes\nscope=$scope\n"; + + xCAT_monitoring::monitorctrl->deconfig([$pname], \@nodes, $scope, $callback, $grands); - xCAT_monitoring::monitorctrl->deconfig([$pname], \@nodes, $scope, $callback); return 0; }