initial commit

master
Bryan Heden 4 years ago
commit 8ed587cfd4

@ -0,0 +1,84 @@
#!/bin/env php -q
<?php
define("SUBSYSTEM", 1);
require_once(dirname(__FILE__) . '/../html/config.inc.php');
require_once(dirname(__FILE__) . '/../html/includes/common.inc.php');
require_once(dirname(__FILE__) . '/../html/includes/components/report_objects_down/report_objects_down.inc.php');
require_once(dirname(__FILE__) . '/../html/includes/components/report_objects_down/report_objects_down.common.php');
init_db();
check_if_now_is_a_good_time_to_send_this_report_and_then_send_it($max_runtime = 62, true);
function init_db()
{
if (db_connect_all() == false) {
echo "ERROR CONNECTING TO DATABASES!\n";
exit();
}
}
function check_if_now_is_a_good_time_to_send_this_report_and_then_send_it($max_runtime, $debug = false)
{
$time = time();
$last_time_report_sent = get_option("report_objects_down_last_sent");
while (time() - $time < $max_runtime) {
$settings_raw = get_option("report_objects_down_options");
if ($settings_raw == "") {
$settings = array();
}
else {
$settings = unserialize($settings_raw);
}
$time_of_day_to_send = grab_array_var($settings, "time", "5:00");
if (strlen($time_of_day_to_send) < 5) {
$time_of_day_to_send = "0" . $time_of_day_to_send;
}
$time_of_day_to_send = "18:48";
// check if now is the time to send
if (date("Y-m-d H:i:s") == date("Y-m-d") . " " . $time_of_day_to_send . ":00"
|| time() - $last_time_report_sent >= 24 * 60 * 60) {
// if another process has updated the last_time_report_sent since we've executed
// we'll send duplicate emails - so do a last minute panic check here
$new_last_time_report_sent = get_option("report_objects_down_last_sent");
if ($new_last_time_report_sent != $last_time_report_sent) {
if ($debug) {
echo "\nAnother process appears to have handled the report...\n";
exit(0);
}
}
if ($debug) {
echo "\nThe time to send the report is now...\n";
}
if (!generate_csv_reports()) {
echo "\nUnable to generate CSV reports!\n";
exit(1);
}
if (!send_report_email($debug)) {
echo "\nUnable to send CSV reports!\n";
exit(1);
}
set_option("report_objects_down_last_sent", time());
break;
}
echo ".";
sleep(1);
}
}

@ -0,0 +1,83 @@
<?php
require_once(dirname(__FILE__) . "/../../common.inc.php");
require_once(dirname(__FILE__) . "/report_objects_down.common.php");
pre_init();
init_session();
grab_request_vars();
check_prereqs();
check_authentication(false);
generate_report();
generate_csv_reports();
function generate_report()
{
/*
1. Do nothing really, and just report on critical services that are currently critical (my favorite option) - and see if they complain and can come up with better explanation
2. If the duration that the service has been down is greater than 24 hours, exclude it from the report (my second favorite option)
*/
$mode = grab_request_var("mode");
if ($mode != "2") {
$mode = "1";
}
$mode = intval($mode);
do_page_start(array("page_title" => "Objects Down Report"), true);
echo '
<form method="get">
<div class="well report-options form-inline">
<div class="reportoptionpicker">
<div class="input-group" style="margin-right: 10px;">
<label class="input-group-addon">Report Mode</label>
<select id="mode" name="mode" class="form-control">
<option value="1"' . ($mode == "1" ? 'selected="selected"' : '') . '>Currently Critical</option>
<option value="2"' . ($mode == "2" ? 'selected="selected"' : '') . '>Exclude 24+</option>
</select>
</div>
<button type="submit" id="run" class="btn btn-sm btn-primary" name="reportbtn">Run</button>
<div style="clear: both;"></div>
</div>
</div>
</form>
<style>
th,td {
padding: 2px 10px;
}
</style>
';
$hosts = get_objects_down_hosts($mode);
if ($hosts != false) {
echo "<h1>Hosts</h1>";
echo "<table><tr><th>Host Name</th><th>Host Address</th><th>Duration Down (days)</th></tr>";
foreach ($hosts as $host) {
echo "<tr><td>${host['host_name']}</td><td>${host['host_address']}</td><td>${host['duration']}</td></tr>";
}
echo "</table>";
}
else {
echo '<p>No Down Hosts</p>';
}
$services = get_objects_down_services($mode);
if ($services != false) {
echo "<h1>Services</h1>";
echo "<table><tr><th>Host Name</th><th>Host Address</th><th>Service Description</th><th>Status Information</th><th>Duration Down (hours)</th></tr>";
foreach ($services as $service) {
echo "<tr><td>${service['host_name']}</td><td>${service['host_address']}</td><td>${service['svc_desc']}</td><td>${service['svc_status']}</td><td>${service['duration']}</td></tr>";
}
echo "</table>";
}
else {
echo '<p>No Critical Services</p>';
}
}

@ -0,0 +1,278 @@
<?php
/*
Part 1 Hosts Down only at that point in time - Data to Include
Host Name
IP Address
Duration it has been down
*/
// return an array of host data specified in the data above
// or return false and print an error
function get_objects_down_hosts($mode = 1, $return_headers = false)
{
$arr = array();
$hosts_xml = get_xml_host_status(array());
if (!$hosts_xml) {
echo "Something went wrong getting host status!\n";
return false;
}
if ($return_headers == true) {
$arr[] = array("Host Name", "Host Address", "Duration (days)");
}
foreach ($hosts_xml->hoststatus as $host) {
// TODO: should we check on state type as well?
if ($host->current_state != STATE_DOWN) {
continue;
}
$host_arr['host_name'] = (string) $host->name;
$host_arr['host_address'] = (string) $host->address;
$state_change_time = strtotime($host->last_state_change);
// something went wrong with strtotime..
// likely means it's just always been down i suspect
if ($state_change_time == false || $state_change_time == -1) {
$state_change_time = strtotime($host->status_update_time);
// something seriously wrong at this point..
if ($state_change_time == false || $state_change_time == -1) {
continue;
}
}
$host_arr['duration'] = round((time() - $state_change_time) / (24 * 60 * 60), 2);
$arr[] = $host_arr;
}
return $arr;
}
/*
Part 2 Services Down Data to include:
Host Name
IP Address
Service that is down
Status Information ie. SNMP CRITICAL - *0*
Duration it has been down
Simple enough… Now the tricky part. For part 2, I would like excluded from the report the following:
[x] If notifications are disabled for the service, exclude from the report
[x] If the service is down due to “Plugin Timed Out …”, exclude from the report
[x] If the service is down due to the host being down, exclude from the report
Include only from the last 24 hours so day and night time alarms are taken into account
*/
/*
mode:
1. Do nothing really, and just report on critical services that are currently critical (my favorite option) - and see if they complain and can come up with better explanation
2. If the duration that the service has been down is greater than 24 hours, exclude it from the report (my second favorite option)
*/
// returns array of array(hostname, address, service, statustext, duration) - where the above conditions are met
// or return false and print an error
function get_objects_down_services($mode = 1, $return_headers = false)
{
$arr = array();
$services_xml = get_xml_service_status(array());
if (!$services_xml) {
echo "Something went wrong getting service status!\n";
return false;
}
if ($return_headers == true) {
$arr[] = array("Host Name", "Host Address", "Service Description", "Service Status", "Duration (hours)");
}
foreach ($services_xml->servicestatus as $svc) {
$svc_arr = array();
if ($svc->current_state != STATE_CRITICAL) {
continue;
}
if ($svc->notifications_enabled != 1) {
continue;
}
$svc_arr['host_name'] = (string) $svc->host_name;
$svc_arr['host_address'] = (string) $svc->host_address;
$svc_arr['svc_desc'] = (string) $svc->name;
$svc_arr['svc_status'] = (string) $svc->status_text;
if (strpos($svc_arr['svc_status'], "Plugin timed out") !== false) {
continue;
}
$state_change_time = strtotime($svc->last_state_change);
$host_xml = get_xml_host_status(array("name" => $svc_arr['host_name']));
// definitely should have found a host..
if (!$host_xml) {
continue;
}
// definitely should have found only one host..
else if ($host_xml->recordcount != 1) {
continue;
}
else {
// skip services whos host is down
if ($host_xml->hoststatus->current_state == STATE_DOWN) {
continue;
}
}
// something went wrong with strtotime..
// likely means it's just always been down i suspect
if ($state_change_time == false || $state_change_time == -1) {
$state_change_time = strtotime($svc->status_update_time);
// something seriously wrong at this point..
if ($state_change_time == false || $state_change_time == -1) {
continue;
}
}
$svc_arr['duration'] = round((time() - $state_change_time) / (60 * 60), 2);
// skip if we need to
if ($mode == 2) {
if ($svc_arr['duration'] > (24 * 60 * 60)) {
continue;
}
}
$arr[] = $svc_arr;
}
return $arr;
}
function get_csv_output($which)
{
if ($which != "hosts" && $which != "services") {
return "";
}
$arr_func = "get_objects_down_${which}";
$data = $arr_func($mode = 2, $headers = true);
if ($data == false) {
return "";
}
$csv = "";
foreach ($data as $row) {
foreach ($row as $cell) {
$csv .= $cell . ",";
}
$csv .= "\n";
}
return $csv;
}
function generate_csv_reports()
{
$hosts = get_csv_output("hosts");
//echo "<pre>$hosts</pre>";
$services = get_csv_output("services");
//echo "<pre>$services</pre>";
if ($hosts == false) {
echo "\nUnable to retrieve hosts csv report..\n";
}
if ($services == false) {
echo "\nUnable to retrieve services csv report..\n";
}
if ($hosts == false || $services == false) {
echo "testing..\n";
return false;
}
if (file_exists("/usr/local/nagiosxi/tmp/rod_hosts.csv")) {
if (!unlink("/usr/local/nagiosxi/tmp/rod_hosts.csv")) {
echo "\nUnable to delete /usr/local/nagiosxi/tmp/rod_hosts.csv file\n";
return false;
}
}
if (file_exists("/usr/local/nagiosxi/tmp/rod_services.csv")) {
if (!unlink("/usr/local/nagiosxi/tmp/rod_services.csv")) {
echo "\nUnable to delete /usr/local/nagiosxi/tmp/rod_services.csv file\n";
return false;
}
}
if (!file_put_contents("/usr/local/nagiosxi/tmp/rod_hosts.csv", $hosts)) {
echo "\nUnable to write /usr/local/nagiosxi/tmp/rod_hosts.csv file\n";
return false;
}
if (!file_put_contents("/usr/local/nagiosxi/tmp/rod_services.csv", $services)) {
echo "\nUnable to write /usr/local/nagiosxi/tmp/rod_services.csv file\n";
return false;
}
return true;
}
function send_report_email($debug = false)
{
$settings_raw = get_option("report_objects_down_options");
if ($settings_raw == "") {
$settings = array();
}
else {
$settings = unserialize($settings_raw);
}
$recipients = grab_array_var($settings, "recipients", false);
if (empty($recipients)) {
echo "\nNo recipients specified!\n";
return false;
}
$recipients = explode(",", $recipients);
foreach ($recipients as $recipient) {
$options = array(
"referer" => "report_objects_down",
"to" => $recipient,
"subject" => "Objects Down Report - " . date('d-m-Y'),
"high_priority" => true,
"message" => "Objects Down Report",
"plaintext" => "Objects Down Report",
"attachment" => array(
array(
"/usr/local/nagiosxi/tmp/rod_hosts.csv",
"hosts.csv"
),
array(
"/usr/local/nagiosxi/tmp/rod_services.csv",
"services.csv"
),
),
);
$dbg = "";
send_email($options, $dbg, $options["referer"], $options["plaintext"]);
if ($debug) {
echo "send_email debug: $dbg\n";
}
}
return true;
}

@ -0,0 +1,177 @@
<?php
require_once(dirname(__FILE__) . '/../componenthelper.inc.php');
report_objects_down_init();
function report_objects_down_init()
{
$desc = "Report on objects (hosts/services) down.";
if (!report_objects_down_check_version()) {
$desc = $desc . " <strong>Error: This component requires Nagios XI 5.6.0 or later.</strong>";
}
register_component("report_objects_down", array(
COMPONENT_NAME => "report_objects_down",
COMPONENT_AUTHOR => "hedenface",
COMPONENT_DESCRIPTION => $desc,
COMPONENT_TITLE => "Objects Down Report",
COMPONENT_VERSION => "0.0.0",
COMPONENT_DATE => "05/07/2019",
COMPONENT_CONFIGFUNCTION => "report_objects_down_config",
)
);
if (!report_objects_down_check_version()) {
return;
}
register_callback(CALLBACK_MENUS_INITIALIZED, 'report_objects_down_component_addmenu');
}
function report_objects_down_check_version()
{
if (function_exists('get_product_release')) {
if (get_product_release() >= 5600) {
return true;
}
}
return false;
}
function report_objects_down_component_addmenu()
{
$component_url = get_component_url_base("report_objects_down");
$menu_section = find_menu_item(MENU_REPORTS, "menu-reports-nagiosxi", "id");
if ($menu_section == null) {
return false;
}
$order = grab_array_var($menu_section, "order", "");
$new_order = $order + 0.1;
if ($new_order < 0) {
return false;
}
add_menu_item(MENU_REPORTS, array(
"type" => "link",
"title" => "Objects Down",
"id" => "menu-reports-nagiosxi",
"order" => $new_order,
"opts" => array(
"href" => $component_url . "/index.php",
)
));
add_menu_item(MENU_REPORTS, array(
"type" => "linkspacer",
"id" => "menu-reports-avail-report-spacer",
"order" => $new_order + 0.1
));
}
function report_objects_down_config($mode = "", $inargs, &$outargs, &$result)
{
$result = 0;
$output = "";
$component_name = "report_objects_down";
switch ($mode) {
case COMPONENT_CONFIGMODE_GETSETTINGSHTML:
$settings_raw = get_option("report_objects_down_options");
if ($settings_raw == "") {
$settings = array();
}
else {
$settings = unserialize($settings_raw);
}
// initial values
$time_of_day_to_send = grab_array_var($settings, "time", "5:00");
$recipients = grab_array_var($settings, "recipients", false);
// values passed to us
$time_of_day_to_send = grab_array_var($inargs, "time", $time_of_day_to_send);
$recipients = grab_array_var($inargs, "recipients", $recipients);
$output = '
<p>Use the Objects Down Report configuration to adjust the time of day (Monday - Friday) that the report is sent, and who it is sent to.</p>
<h5 class="ul">Objects Down Report</h5>
<table class="table table-condensed table-no-border table-auto-width">
<tr>
<td class="vt">
<label>Time of Day to send report:</label>
</td>
<td>
<input type="text" size="5" name="time" id="time" value="' . htmlentities($time_of_day_to_send) . '" class="form-control">
</td>
</tr>
<tr>
<td class="vt">
<label>Recipients (comma separated):</label>
</td>
<td>
<input type="text" size="50" name="recipients" id="recipients" value="' . htmlentities($recipients) . '" class="form-control">
</td>
</tr>
</table>';
break;
case COMPONENT_CONFIGMODE_SAVESETTINGS:
// get variables
$time_of_day_to_send = grab_array_var($inargs, "time", "5:00");
$recipients = grab_array_var($inargs, "recipients", "");
// validate variables
$errors = 0;
$errmsg = array();
if (!is_valid_time_of_day($time_of_day_to_send)) {
$errmsg[$errors++] = "Invalid time specified [00-23]:[00-59]";
}
// handle errors
if ($errors > 0) {
$outargs[COMPONENT_ERROR_MESSAGES] = $errmsg;
$result = 1;
return '';
}
// save settings
$settings = array(
"time" => $time_of_day_to_send,
"recipients" => $recipients,
);
set_option("report_objects_down_options", serialize($settings));
break;
default:
break;
}
return $output;
}
function is_valid_time_of_day($time)
{
if (strlen($time) < 5) {
$time = "0" . $time;
}
$format = "Y-m-d H:i:s";
$date = date("Y-m-d") . " $time:00";
$dateObj = DateTime::createFromFormat($format, $date);
return $dateObj && $dateObj->format($format) == $date;
}

@ -0,0 +1,177 @@
<?php
require_once(dirname(__FILE__) . '/../componenthelper.inc.php');
report_objects_down_init();
function report_objects_down_init()
{
$desc = "Report on objects (hosts/services) down.";
if (!report_objects_down_check_version()) {
$desc = $desc . " <strong>Error: This component requires Nagios XI 5.6.0 or later.</strong>";
}
register_component("report_objects_down", array(
COMPONENT_NAME => "report_objects_down",
COMPONENT_AUTHOR => "hedenface",
COMPONENT_DESCRIPTION => $desc,
COMPONENT_TITLE => "Objects Down Report",
COMPONENT_VERSION => "0.0.0",
COMPONENT_DATE => "05/07/2019",
COMPONENT_CONFIGFUNCTION => "report_objects_down_config",
)
);
if (!report_objects_down_check_version()) {
return;
}
register_callback(CALLBACK_MENUS_INITIALIZED, 'report_objects_down_component_addmenu');
}
function report_objects_down_check_version()
{
if (function_exists('get_product_release')) {
if (get_product_release() >= 5600) {
return true;
}
}
return false;
}
function report_objects_down_component_addmenu()
{
$component_url = get_component_url_base("report_objects_down");
$menu_section = find_menu_item(MENU_REPORTS, "menu-reports-nagiosxi", "id");
if ($menu_section == null) {
return false;
}
$order = grab_array_var($menu_section, "order", "");
$new_order = $order + 0.1;
if ($new_order < 0) {
return false;
}
add_menu_item(MENU_REPORTS, array(
"type" => "link",
"title" => "Objects Down",
"id" => "menu-reports-nagiosxi",
"order" => $new_order,
"opts" => array(
"href" => $component_url . "/index.php",
)
));
add_menu_item(MENU_REPORTS, array(
"type" => "linkspacer",
"id" => "menu-reports-avail-report-spacer",
"order" => $new_order + 0.1
));
}
function report_objects_down_config($mode = "", $inargs, &$outargs, &$result)
{
$result = 0;
$output = "";
$component_name = "report_objects_down";
switch ($mode) {
case COMPONENT_CONFIGMODE_GETSETTINGSHTML:
$settings_raw = get_option("report_objects_down_options");
if ($settings_raw == "") {
$settings = array();
}
else {
$settings = unserialize($settings_raw);
}
// initial values
$time_of_day_to_send = grab_array_var($settings, "time", "5:00");
$recipients = grab_array_var($settings, "recipients", false);
// values passed to us
$time_of_day_to_send = grab_array_var($inargs, "time", $time_of_day_to_send);
$recipients = grab_array_var($inargs, "recipients", $recipients);
$output = '
<p>Use the Objects Down Report configuration to adjust the time of day (Monday - Friday) that the report is sent, and who it is sent to.</p>
<h5 class="ul">Objects Down Report</h5>
<table class="table table-condensed table-no-border table-auto-width">
<tr>
<td class="vt">
<label>Time of Day to send report:</label>
</td>
<td>
<input type="text" size="5" name="time" id="time" value="' . htmlentities($time_of_day_to_send) . '" class="form-control">
</td>
</tr>
<tr>
<td class="vt">
<label>Recipients (comma separated):</label>
</td>
<td>
<input type="text" size="50" name="recipients" id="recipients" value="' . htmlentities($recipients) . '" class="form-control">
</td>
</tr>
</table>';
break;
case COMPONENT_CONFIGMODE_SAVESETTINGS:
// get variables
$time_of_day_to_send = grab_array_var($inargs, "time", "5:00");
$recipients = grab_array_var($inargs, "recipients", "");
// validate variables
$errors = 0;
$errmsg = array();
if (!is_valid_time_of_day($time_of_day_to_send)) {
$errmsg[$errors++] = "Invalid time specified [00-23]:[00-59]";
}
// handle errors
if ($errors > 0) {
$outargs[COMPONENT_ERROR_MESSAGES] = $errmsg;
$result = 1;
return '';
}
// save settings
$settings = array(
"time" => $time_of_day_to_send,
"recipients" => $recipients,
);
set_option("report_objects_down_options", serialize($settings));
break;
default:
break;
}
return $output;
}
function is_valid_time_of_day($time)
{
if (strlen($time) < 5) {
$time = "0" . $time;
}
$format = "Y-m-d H:i:s";
$date = date("Y-m-d") . " $time:00";
$dateObj = DateTime::createFromFormat($format, $date);
return $dateObj && $dateObj->format($format) == $date;
}

@ -0,0 +1,10 @@
#!/bin/bash
if [ -f cron.php ]; then
cp cron.php /usr/local/nagiosxi/cron/report_objects_down.cron.php
chown nagios:nagios /usr/local/nagiosxi/cron/report_objects_down.cron.php
echo "* * * * * nagios /usr/bin/php -q /usr/local/nagiosxi/cron/report_objects_down.cron.php >> /usr/local/nagiosxi/var/report_objects_down.log 2>&1" >> /etc/cron.d/nagiosxi
else
echo "Please run this setup.sh from within the component directory"
exit 1
fi
Loading…
Cancel
Save