Monitored host not displaying

Support forum for Nagios Core, Nagios Plugins, NCPA, NRPE, NSCA, NDOUtils and more. Engage with the community of users including those using the open source solutions.
npolovenko
Support Tech
Posts: 3457
Joined: Mon May 15, 2017 5:00 pm

Re: Monitored host not displaying

Post by npolovenko »

@karl, No problem at all. Looks like you don't have the actual NCPA plugin in the directory. So go to

Code: Select all

/usr/local/nagios/libexec
That's where all the plugins are. Then lets create the plugin that it's looking for:

Code: Select all

nano check_ncpa.py 
Then copy and paste this contents to the file:

Code: Select all

#!/usr/bin/env python
"""
SYNOPSIS
"""
import sys
import optparse
import traceback
import ssl

# Python 2/3 Compatibility imports

try:
    import json
except ImportError:
    import simplejson as json

try:
    import urllib.request
    import urllib.parse
    import urllib.error
except ImportError:
    import urllib2
    import urllib

try:
    urlencode = urllib.parse.urlencode
except AttributeError:
    urlencode = urllib.urlencode

try:
    urlopen = urllib.request.urlopen
except AttributeError:
    urlopen = urllib2.urlopen

try:
    urlquote = urllib.parse.quote
except AttributeError:
    urlquote = urllib.quote

import shlex
import re
import signal


__VERSION__ = '1.1.1'


def parse_args():
    version = 'check_ncpa.py, Version %s' % __VERSION__

    parser = optparse.OptionParser()
    parser.add_option("-H", "--hostname", help="The hostname to be connected to.")
    parser.add_option("-M", "--metric", default='',
                      help="The metric to check, this is defined on client "
                           "system. This would also be the plugin name in the "
                           "plugins directory. Do not attach arguments to it, "
                           "use the -a directive for that. DO NOT INCLUDE the api/ "
                           "instruction.")
    parser.add_option("-P", "--port", default=5693, type="int",
                      help="Port to use to connect to the client.")
    parser.add_option("-w", "--warning", default=None, type="str",
                      help="Warning value to be passed for the check.")
    parser.add_option("-c", "--critical", default=None, type="str",
                      help="Critical value to be passed for the check.")
    parser.add_option("-u", "--units", default=None,
                      help="The unit prefix (k, Ki, M, Mi, G, Gi, T, Ti) for b and B unit "
                           "types which calculates the value returned.")
    parser.add_option("-n", "--unit", default=None,
                      help="Overrides the unit with whatever unit you define. "
                           "Does not perform calculations. This changes the unit of measurement only.")
    parser.add_option("-a", "--arguments", default=None,
                      help="Arguments for the plugin to be run. Not necessary "
                           "unless you're running a custom plugin. Given in the same "
                           "as you would call from the command line. Example: -a '-w 10 -c 20 -f /usr/local'")
    parser.add_option("-t", "--token", default='',
                      help="The token for connecting.")
    parser.add_option("-T", "--timeout", default=60, type="int",
                      help="Enforced timeout, will terminate plugins after "
                           "this amount of seconds. [%default]")
    parser.add_option("-d", "--delta", action='store_true',
                      help="Signals that this check is a delta check and a "
                           "local state will kept.")
    parser.add_option("-l", "--list", action='store_true',
                      help="List all values under a given node. Do not perform "
                           "a check.")
    parser.add_option("-v", "--verbose", action='store_true',
                      help='Print more verbose error messages.')
    parser.add_option("-D", "--debug", action='store_true',
                      help='Print LOTS of error messages. Used mostly for debugging.')
    parser.add_option("-V", "--version", action='store_true',
                      help='Print version number of plugin.')
    parser.add_option("-q", "--queryargs", default=None,
                      help='Extra query arguments to pass in the NCPA URL.')
    parser.add_option("-s", "--secure", action='store_true', default=False,
                      help='Require successful certificate verification. Does not work on Python < 2.7.9.')
    parser.add_option("-p", "--performance", action='store_true', default=False,
                      help='Print performance data even when there is none. '
                           'Will print data matching the return code of this script')
    options, _ = parser.parse_args()

    if options.version:
        print(version)
        sys.exit(0)

    if options.arguments and options.metric and not 'plugin' in options.metric:
        parser.print_help()
        parser.error('You cannot specify arguments without running a custom plugin.')

    if not options.hostname:
        parser.print_help()
        parser.error("Hostname is required for use.")

    elif not options.metric and not options.list:
        parser.print_help()
        parser.error('No metric given, if you want to list all possible items '
                     'use --list.')

    options.metric = re.sub(r'^/?(api/)?', '', options.metric)

    return options


# ~ The following are all helper functions. I would normally split these out into
# ~ a new module but this needs to be portable.


def get_url_from_options(options):
    host_part = get_host_part_from_options(options)
    arguments = get_arguments_from_options(options)
    return '%s?%s' % (host_part, arguments)


def get_host_part_from_options(options):
    """Gets the address that will be queries for the JSON.
    """
    hostname = options.hostname
    port = options.port

    if not options.metric is None:
        metric = urlquote(options.metric)
    else:
        metric = ''

    arguments = get_check_arguments_from_options(options)
    if not metric and not arguments:
        api_address = 'https://%s:%d/api' % (hostname, port)
    else:
        api_address = 'https://%s:%d/api/%s/%s' % (hostname, port, metric, arguments)

    return api_address


def get_check_arguments_from_options(options):
    """Gets the escaped URL for plugin arguments to be added
    to the end of the host URL. This is different from the get_arguments_from_options
    in that this is meant for the syntax when the user is calling a check, whereas the below
    is when GET arguments need to be added.
    """
    arguments = options.arguments
    if arguments is None:
        return ''
    else:
        lex = shlex.shlex(arguments)
        lex.whitespace_split = True
        arguments = '/'.join([urlquote(x, safe='') for x in lex])
        return arguments


def get_arguments_from_options(options, **kwargs):
    """Returns the http query arguments. If there is a list variable specified,
    it will return the arguments necessary to query for a list.
    """

    # Note: Changed back to units due to the units being what is passed via the
    # API call which can confuse people if they don't match
    arguments = { 'token': options.token,
                  'units': options.units }
    
    if not options.list:
        arguments['warning'] = options.warning
        arguments['critical'] = options.critical
        arguments['delta'] = options.delta
        arguments['check'] = 1
        arguments['unit'] = options.unit

    args = list((k, v) for k, v in list(arguments.items()) if v is not None)

    # Get the options (comma separated)
    if options.queryargs:
        for argument in options.queryargs.split(','):
            key, value = argument.split('=')
            if value is not None:
                args.append((key, value))

    #~ Encode the items in the dictionary that are not None
    return urlencode(args)


def get_json(options):
    """Get the page given by the options. This will call down the url and
    encode its finding into a Python object (from JSON).
    """
    url = get_url_from_options(options)

    if options.verbose:
        print('Connecting to: ' + url)

    try:
        ctx = ssl.create_default_context()
        if not options.secure:
            ctx.check_hostname = False
            ctx.verify_mode = ssl.CERT_NONE
        ret = urlopen(url, context=ctx)
    except AttributeError:
        ret = urlopen(url)

    ret = ''.join(ret)

    if options.verbose:
        print('File returned contained:\n' + ret)

    arr = json.loads(ret)

    if 'value' in arr:
        return arr['value']

    return arr


def run_check(info_json):
    """Run a check against the remote host.
    """
    return info_json['stdout'], info_json['returncode']


def show_list(info_json):
    """Show the list of available options.
    """
    return json.dumps(info_json, indent=4), 0


def timeout_handler(threshold):
    def wrapped(signum, frames):
        stdout = "UNKNOWN: Execution exceeded timeout threshold of %ds" % threshold
        print stdout
        sys.exit(3)
    return wrapped


def main():
    options = parse_args()

    # We need to ensure that we will only execute for a certain amount of
    # seconds.
    signal.signal(signal.SIGALRM, timeout_handler(options.timeout))
    signal.alarm(options.timeout)

    try:

        if options.version:
            stdout = 'The version of this plugin is %s' % __VERSION__
            return stdout, 0

        info_json = get_json(options)
        if options.list:
            return show_list(info_json)
        else:
            stdout, returncode = run_check(info_json)
            if options.performance and stdout.find("|") == -1:
                performance = " | 'status'={};1;2;".format(returncode)
                return "{}{}".format(stdout, performance), returncode
            else:
                return stdout, returncode
    except Exception, e:
        if options.debug:
            return 'The stack trace:' + traceback.format_exc(), 3
        elif options.verbose:
            return 'An error occurred:' + str(e), 3
        else:
            return 'UNKNOWN: Error occurred while running the plugin. Use the verbose flag for more details.', 3


if __name__ == "__main__":
    stdout, returncode = main()
    print(stdout)
    sys.exit(returncode)
Exit and save the file. Then change permissions for the plugin so that Nagios can acess it:

Code: Select all

chmod +x check_ncpa.py
Finally restart Nagios again

Code: Select all

service nagios restart
That's it. You can go to Nagios Core web interface and all services should show the output. But give it a few minutes in order for all service checks to start working.

And, moving forward. You're probably wondering how to fix this:
Untitled.png
Untitled.png (2.57 KiB) Viewed 4756 times
Go to

Code: Select all

/usr/local/nagios/share/images/logos
And do something like

Code: Select all

cp debian.png ncpa.png
That should do it.
As of May 25th, 2018, all communications with Nagios Enterprises and its employees are covered under our new Privacy Policy.
karl
Posts: 11
Joined: Wed Oct 11, 2017 4:16 am

Re: Monitored host not displaying

Post by karl »

Hi,

I'm back from my holiday and have tried your suggestion however i'm still getting

(Return code of 127 is out of bounds - plugin may be missing : (No output on stdout) stderr: /usr/bin/env: ‘python’: No such file or directory))

The check_ncpa.py file was already there and had all of what you sent in there already.

On a plus note the small image now displays lol
npolovenko
Support Tech
Posts: 3457
Joined: Mon May 15, 2017 5:00 pm

Re: Monitored host not displaying

Post by npolovenko »

karl wrote: On a plus note the small image now displays lol
Great, i think the issue should be considered resolved now! :D

Can you navigate to:

Code: Select all

/usr/local/nagios/libexec/
and attempt to run:

Code: Select all

./check_ncpa.py
Does the plugin give you out of bounds errors or it works fine?
If it does give you errors you need to make sure that Python is actually installed on your system, and set up a $PATH variable.
You can run:

Code: Select all

which python
And change the first line of code in your plugin to the appropriate path.

But if the plugin worked fine from the command line please run:
chmod +x check_ncpa.py
chown nagios:nagios check_ncpa.py

After that restart nagios with

Code: Select all

service nagios restart
As of May 25th, 2018, all communications with Nagios Enterprises and its employees are covered under our new Privacy Policy.
karl
Posts: 11
Joined: Wed Oct 11, 2017 4:16 am

Re: Monitored host not displaying

Post by karl »

when I run

Code: Select all

./check_ncpa.py
it tells me

/usr/bin/env: 'python' : No such file or directory
dwhitfield
Former Nagios Staff
Posts: 4583
Joined: Wed Sep 21, 2016 10:29 am
Location: NoLo, Minneapolis, MN
Contact:

Re: Monitored host not displaying

Post by dwhitfield »

We need to see the output of which python. This looks like ubuntu, but what version?
npolovenko
Support Tech
Posts: 3457
Joined: Mon May 15, 2017 5:00 pm

Re: Monitored host not displaying

Post by npolovenko »

@karl, Right, so the script can't find Python executable files.
Please run:

Code: Select all

which python
find /usr -type f -name 'python*' -perm -a+x
And send us the outputs.

The first line of the check_ncpa says:
#!/usr/bin/env python. We need to change this path to point to the right directory with Python executables.
As of May 25th, 2018, all communications with Nagios Enterprises and its employees are covered under our new Privacy Policy.
karl
Posts: 11
Joined: Wed Oct 11, 2017 4:16 am

Re: Monitored host not displaying

Post by karl »

Ok so I found that the path to python was

Code: Select all

/usr/bin/python3.5m
I changed it in the check_ncpa.py file and tried to run it

i'm now getting

Code: Select all

File "./check_ncpa.py", line 282
except Exception, e:
                ^

SyntaxError: invalid syntax
npolovenko
Support Tech
Posts: 3457
Joined: Mon May 15, 2017 5:00 pm

Re: Monitored host not displaying

Post by npolovenko »

@karl, The Python version that you have installed has a slightly different syntax.
In your plugin "./check_ncpa.py" on line 282
change:

Code: Select all

except Exception, e:
to
except Exception as e:
That's one way to fix it. Another way would be to specify an older version of Python to run the script:
At the top of the script where you specified the path add the older version number: 2.6 or 2.7. Like this:

Code: Select all

 #!/usr/bin/env python2.6.6
That should do it.
As of May 25th, 2018, all communications with Nagios Enterprises and its employees are covered under our new Privacy Policy.
zulash
Posts: 1
Joined: Sun Nov 05, 2017 11:57 am
Contact:

Re: Monitored host not displaying

Post by zulash »

try read this article https://support.nagios.com/kb/article/n ... ssing.html im sure it ill help
karl
Posts: 11
Joined: Wed Oct 11, 2017 4:16 am

Re: Monitored host not displaying

Post by karl »

Hi, sorry i've had a few days off work.

I have changed line 282 to say 'as e' i've now got

UNKNOWN: Error occurred while running the plugin. Use the verbose flag for more details

Image
Locked