Page 1 of 1

report for hosts and services not in groups

Posted: Tue Aug 08, 2023 11:14 am
by markjgreene
Is there a method or an already existing report to find hosts not in host groups and services not in service groups for XI v5.8.5 ?

Thanks!
mark greene

Re: report for hosts and services not in groups

Posted: Wed Aug 09, 2023 12:17 pm
by eloyd
Not inherently within XI. But you can cheat a little bit and use the API to find things out. Click on "Help" and then "Objects Reference" within XI and you'll be greeted with a bunch of API calls that you can make to query the host groups. To my knowledge, no one has written an API to the parser to see exactly what Nagios Core sees when it unwinds the config files, but you can use "jq" and bash to traipse through the JSON list of groups and then groupmembers to see what's in every group. Then combine that list with the list of all hosts and figure out what's not in a group.

It's not neccessarily easy, but it should be relatively straightforward.

Re: report for hosts and services not in groups

Posted: Wed Aug 09, 2023 1:18 pm
by danderson
I made a little script based on what @eloyd said

Code: Select all

#!/bin/bash

key=""
xi=""

function usage() {
        echo ""
        echo "Usage: $0 -k \"API Key\" -x \"XI Hostname\""
        echo "Usage: $0 -h,--help"
        echo ""
        echo "Options:"
        echo " -k,--key     API Key         XI API Key"
        echo " -x,--xi      XI Hostname     Hostname of XI server"
        echo ""
}

if [ $# -eq 0 ]; then
        usage
        exit 1
fi

while [ "$1" != "" ]
do
    case "$1" in
        -k | --key) key=$2; shift 2;;
        -x | --xi) xi=$2; shift 2;;
        -h | --help) usage; exit 0;;
        *) usage; exit 1;;
    esac
done

if [ -z $key ]; then
    echo "No API key specified"
    exit 1
fi

if [ -z $xi ]; then
    echo "No XI hostname specified"
    exit 1
fi

hostgroupmembers="$(curl -s -XGET "http://$xi/nagiosxi/api/v1/objects/hostgroupmembers?apikey=$key&pretty=1" | grep "host_name" | sed -e 's/^[ \t]*//;s/,*[ \t]*$//')"
hosts="$(curl -s -XGET "http://$xi/nagiosxi/api/v1/objects/host?apikey=$key&pretty=1" | grep "host_name" | sed -e 's/^[ \t]*//;s/,*[ \t]*$//')"

servicegroupmembers="$(curl -s -XGET "http://$xi/nagiosxi/api/v1/objects/servicegroupmembers?apikey=$key&pretty=1" | grep "service_description" | sed -e 's/^[ \t]*//;s/,*[ \t]*$//')"
services="$(curl -s -XGET "http://$xi/nagiosxi/api/v1/objects/service?apikey=$key&pretty=1" | grep "service_description" | sed -e 's/^[ \t]*//;s/,*[ \t]*$//')"
# echo -e "Hostgroup members:\n$hostgroupmembers\n"
# echo -e "Hosts:\n$hosts\n"
# echo -e "Servicegroup members:\n$servicegroupmembers\n"
# echo -e "Services:\n$services\n"

echo "Hosts not in Hostgroups:"
echo "$(diff --suppress-common-lines <(echo "$hosts") <(echo "$hostgroupmembers") | grep "host_name" | sed -e 's/^< "host_name": //')"
echo ""
echo "Services not in Servicegroups"
echo "$(diff --suppress-common-lines <(echo "$services") <(echo "$servicegroupmembers") | grep "service_description" | sed -e 's/^< "service_description": //')"

exit 0
You could probably do things a little be different with the sed's and the diffs, but this is the general strategy.

Re: report for hosts and services not in groups

Posted: Wed Aug 09, 2023 1:21 pm
by eloyd
Nice! That's pretty much what I was suggesting. And I love it when someone else does the work for me. :-)

Re: report for hosts and services not in groups

Posted: Wed Aug 09, 2023 3:05 pm
by danderson
If you want it in php and with arrays you can manipulate further, try

Code: Select all

<?php 

$key = "";
$xi = "";
$shortopts = "";
$longopts = array();
$name = basename(__FILE__, "");
$hosts = array();
$hostgroupmembers = array();
$services = array();
$servicegroupmembers = array();

// Short options
$shortopts .= "k:";
$shortopts .= "x:";
$shortopts .= "h";

// Long options
$longopts[] = "key:";
$longopts[] = "xi:";
$longopts[] = "help";

$values = getopt($shortopts, $longopts);

function print_usage($name) {
    echo "\nUsage: php ./$name -k \"API Key\" -x \"XI Hostname\"\n";
    echo "Usage: php ./$name --key \"API Key\" --xi \"XI Hostname\"\n";
    echo "Usage: php ./$name -h,--help\n";
    echo "Options:\n";
    echo " -k,--key     API Key         XI API Key\n";
    echo " -x,--xi      XI Hostname     Hostname of XI server\n\n";
    exit(0);
}

if (empty($values)) {
    print_usage($name);
}

if (isset($values["help"]) || isset($values["h"])) {
    print_usage($name);
}

if (empty($values["k"]) && empty($values["key"])) {
    echo "No API key specified\n";
    exit(1);
} else if (!empty($values["k"]) && !empty($values["key"])) {
    echo "Too many API keys specified\n";
    exit(1);
} else {
    if (empty($values["k"])) {
        if (is_array($values["key"])) {
            echo "Too many API keys specified\n";
            exit(1);
        }
        $key = $values["key"];
    } else {
        if (is_array($values["k"])) {
            echo "Too many API keys specified\n";
            exit(1);
        }
        $key = $values["k"];
    }
}

if (empty($values["x"]) && empty($values["xi"])) {
    echo "No XI specified\n";
    exit(1);
} else if (!empty($values["x"]) && !empty($values["xi"])) {
    echo "Too many XIs specified\n";
    exit(1);
} else {
    if (empty($values["x"])) {
        if (is_array($values["xi"])) {
            echo "Too many XIs specified\n";
            exit(1);
        }
        $xi = $values["xi"];
    } else {
        if (is_array($values["x"])) {
            echo "Too many XIs specified\n";
            exit(1);
        }
        $xi = $values["x"];
    }
}

$hoststring = file_get_contents("http://$xi/nagiosxi/api/v1/objects/host?apikey=$key");
$hostjson = json_decode($hoststring, true);

$servicestring = file_get_contents("http://$xi/nagiosxi/api/v1/objects/service?apikey=$key");
$servicejson = json_decode($servicestring, true);

$hostmemberstring = file_get_contents("http://$xi/nagiosxi/api/v1/objects/hostgroupmembers?apikey=$key");
$hostmemberjson = json_decode($hostmemberstring, true);

$servicememberstring = file_get_contents("http://$xi/nagiosxi/api/v1/objects/servicegroupmembers?apikey=$key");
$servicememberjson = json_decode($servicememberstring, true);

array_walk_recursive($hostjson, function ($value, $key) use (&$hosts) {
    if ($key == "host_name") {
        $hosts[] = $value;
    }
});

array_walk_recursive($servicejson, function ($value, $key) use (&$services) {
    if ($key == "service_description") {
        $services[] = $value;
    }
});

array_walk_recursive($hostmemberjson, function ($value, $key) use (&$hostgroupmembers) {
    if ($key == "host_name") {
        $hostgroupmembers[] = $value;
    }
});

array_walk_recursive($servicememberjson, function ($value, $key) use (&$servicegroupmembers) {
    if ($key == "service_description") {
        $servicegroupmembers[] = $value;
    }
});


$uniquehosts = array_diff($hosts, $hostgroupmembers);
$uniqueservices = array_diff($services, $servicegroupmembers);

print_r($uniquehosts);
print_r($uniqueservices);

?>

Re: report for hosts and services not in groups

Posted: Mon Aug 14, 2023 8:42 am
by markjgreene
Thank you all for the replies, I appreciate that. My apologies for not replying sooner. I found a direct MySQL solution as well:

SELECT name1 as host_name
FROM nagios_objects
WHERE object_id NOT IN (SELECT host_object_id from nagios_hostgroup_members)
AND is_active=1
AND objecttype_id=1;

Obviously, this requires direct access to the host running the MySQL db for the Nagios XI system and the credentials used by the XI processes to access the Nagios db, so this is not going to be a generally applicable solution for everyone.

mark

Re: report for hosts and services not in groups

Posted: Wed Nov 29, 2023 3:36 pm
by eloyd
You also run the risk that the database schema changes between releases. The API exists to make sure you always have a supported method of getting information. I'd suggest you switch to it rather the SQL queries.