Should be final build.sh for bare -> Nagios core
This commit is contained in:
Binary file not shown.
@@ -38,7 +38,7 @@ sudo usermod -aG nagcmd nagios
|
|||||||
sudo usermod -aG nagcmd www-data
|
sudo usermod -aG nagcmd www-data
|
||||||
cd /tmp
|
cd /tmp
|
||||||
wget https://assets.nagios.com/downloads/nagioscore/releases/nagios-4.5.12.tar.gz
|
wget https://assets.nagios.com/downloads/nagioscore/releases/nagios-4.5.12.tar.gz
|
||||||
tar -xzf nagios-4.5.12.tar.gz
|
tar -xzf nagios-4.5.12.tar.gz && rm nagios-4.5.12.tar.gz
|
||||||
cd nagios-4.5.12
|
cd nagios-4.5.12
|
||||||
./configure --with-command-group=nagcmd
|
./configure --with-command-group=nagcmd
|
||||||
make all
|
make all
|
||||||
@@ -55,7 +55,7 @@ do_done
|
|||||||
do_msg "Installing Nagios plugins"
|
do_msg "Installing Nagios plugins"
|
||||||
cd /tmp
|
cd /tmp
|
||||||
wget https://nagios-plugins.org/download/nagios-plugins-2.4.11.tar.gz
|
wget https://nagios-plugins.org/download/nagios-plugins-2.4.11.tar.gz
|
||||||
tar -xzf nagios-plugins-2.4.11.tar.gz
|
tar -xzf nagios-plugins-2.4.11.tar.gz && rm nagios-plugins-2.4.11.tar.gz
|
||||||
cd nagios-plugins-2.4.11
|
cd nagios-plugins-2.4.11
|
||||||
./configure --with-nagios-user=nagios --with-nagios-group=nagios
|
./configure --with-nagios-user=nagios --with-nagios-group=nagios
|
||||||
make
|
make
|
||||||
@@ -73,26 +73,29 @@ do_done
|
|||||||
### Installing NCPA and the like, getting the box to monitor itself via NCPA
|
### Installing NCPA and the like, getting the box to monitor itself via NCPA
|
||||||
# Install check_ncpa (C code from beta test)
|
# Install check_ncpa (C code from beta test)
|
||||||
do_msg "Installing NCPA"
|
do_msg "Installing NCPA"
|
||||||
###
|
arch=$(uname -m)
|
||||||
##
|
file="check_ncpa.${arch}"
|
||||||
# FIX
|
if [ -r "$file" ]; then
|
||||||
##
|
echo "Will install $file, since it's here..."
|
||||||
###
|
echo "==> Installing ${file} to /usr/local/nagios/libexec..."
|
||||||
sudo wget -O /usr/local/nagios/libexec/check_ncpa https://git.everwatch.global/eloyd/NWC2026-Fusion/raw/branch/main/check_ncpa
|
sudo install -d /usr/local/nagios/libexec
|
||||||
sudo chown nagios:nagios /usr/local/nagios/libexec/check_ncpa
|
sudo install -m 0755 ${file} /usr/local/nagios/libexec/check_ncpa
|
||||||
sudo chmod 755 /usr/local/nagios/libexec/check_ncpa
|
echo "==> Installation complete!"
|
||||||
|
echo "Installed to: /usr/local/nagios/libexec/check_ncpa"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "### IMPORTANT:"
|
||||||
|
echo "### You must extract, compile, and install the check_ncpa_c.2.Mar-05-26.tgz beta code to /usr/local/nagios/libexec"
|
||||||
|
echo "### Failure to do so will result in service check failures that may be hard to diagnose."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
### Verify
|
### Verify
|
||||||
/usr/local/nagios/libexec/check_ncpa --version
|
/usr/local/nagios/libexec/check_ncpa --version
|
||||||
### Output: check_ncpa.c, Version 1.2.4
|
### Output: check_ncpa.c, Version 1.2.4
|
||||||
|
|
||||||
# Install NCPA Agent
|
# Install NCPA Agent
|
||||||
###
|
cd ~/NWC2026-Fusion
|
||||||
##
|
sudo apt install ./ncpa_3.3.1-1_armhf.deb
|
||||||
# FIX
|
|
||||||
##
|
|
||||||
###
|
|
||||||
sudo wget -O /tmp/ncpa_3.3.1-1_armhf.deb /tmp https://git.everwatch.global/eloyd/NWC2026-Fusion/raw/branch/main/ncpa_3.3.1-1_armhf.deb
|
|
||||||
sudo apt install /tmp/ncpa_3.3.1-1_armhf.deb
|
|
||||||
### Verify
|
### Verify
|
||||||
/usr/local/nagios/libexec/check_ncpa -H localhost -t mytoken -M system/version
|
/usr/local/nagios/libexec/check_ncpa -H localhost -t mytoken -M system/version
|
||||||
### Output: OK: Version was #1 SMP Raspbian 1:6.12.75-1+rpt1 (2026-03-11) | 'version'=#1 SMP Raspbian 1:6.12.75-1+rpt1 (2026-03-11);;;
|
### Output: OK: Version was #1 SMP Raspbian 1:6.12.75-1+rpt1 (2026-03-11) | 'version'=#1 SMP Raspbian 1:6.12.75-1+rpt1 (2026-03-11);;;
|
||||||
@@ -104,13 +107,7 @@ cd /usr/local/nagios/etc/
|
|||||||
sudo mkdir EWG && sudo chown nagios:nagios EWG
|
sudo mkdir EWG && sudo chown nagios:nagios EWG
|
||||||
sudo /bin/sh -c 'grep -q "cfg_dir=/usr/local/nagios/etc/EWG" nagios.cfg && echo "cfg_dir line already added." || echo "cfg_dir=/usr/local/nagios/etc/EWG" >> nagios.cfg'
|
sudo /bin/sh -c 'grep -q "cfg_dir=/usr/local/nagios/etc/EWG" nagios.cfg && echo "cfg_dir line already added." || echo "cfg_dir=/usr/local/nagios/etc/EWG" >> nagios.cfg'
|
||||||
cd EWG
|
cd EWG
|
||||||
###
|
sudo tar xvfz ~/NWC2026-Fusion/EWG_configs.tar.gz && sudo rm EWG_configs.tar.gz
|
||||||
##
|
|
||||||
# FIX
|
|
||||||
##
|
|
||||||
###
|
|
||||||
sudo wget https://git.everwatch.global/eloyd/NWC2026-Fusion/raw/branch/main/EWG_configs.tar.gz
|
|
||||||
sudo tar xvfz EWG_configs.tar.gz && sudo rm EWG_configs.tar.gz
|
|
||||||
sudo sed -i -e "s/localhost:NCPA/${HOSTNAME}/g" *.cfg
|
sudo sed -i -e "s/localhost:NCPA/${HOSTNAME}/g" *.cfg
|
||||||
### Verify
|
### Verify
|
||||||
sudo /usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
|
sudo /usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+357
@@ -0,0 +1,357 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
try:
|
||||||
|
urlerror = urllib.error.URLError
|
||||||
|
except AttributeError:
|
||||||
|
urlerror = urllib2.URLError
|
||||||
|
|
||||||
|
try:
|
||||||
|
httperror = urllib.error.HTTPError
|
||||||
|
except AttributeError:
|
||||||
|
httperror = urllib2.HTTPError
|
||||||
|
|
||||||
|
import shlex
|
||||||
|
import re
|
||||||
|
import signal
|
||||||
|
|
||||||
|
|
||||||
|
__VERSION__ = '1.2.4'
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionError(Exception):
|
||||||
|
error_output_prefix = "UNKNOWN: An error occurred connecting to API. "
|
||||||
|
pass
|
||||||
|
|
||||||
|
class URLError(ConnectionError):
|
||||||
|
def __init__(self, error_message):
|
||||||
|
self.error_message = ConnectionError.error_output_prefix + "(Connection error: '" + error_message + "')"
|
||||||
|
|
||||||
|
class HTTPError(ConnectionError):
|
||||||
|
def __init__(self, error_message):
|
||||||
|
self.error_message = ConnectionError.error_output_prefix + "(HTTP error: '" + error_message + "')"
|
||||||
|
|
||||||
|
|
||||||
|
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=55, 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 each comma, perform lookahead, split if we aren't inside quotes.
|
||||||
|
arguments_list = re.split(''',(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', options.queryargs)
|
||||||
|
for argument in arguments_list:
|
||||||
|
key, value = argument.split('=', 1)
|
||||||
|
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:
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
except httperror as e:
|
||||||
|
try:
|
||||||
|
raise HTTPError('{0} {1}'.format(e.code, e.reason))
|
||||||
|
except AttributeError:
|
||||||
|
raise HTTPError('{0}'.format(e.code))
|
||||||
|
except urlerror as e:
|
||||||
|
raise URLError('{0}'.format(e.reason))
|
||||||
|
|
||||||
|
ret = ret.read()
|
||||||
|
|
||||||
|
if options.verbose:
|
||||||
|
print('File returned contained:\n' + ret.decode('utf-8'))
|
||||||
|
|
||||||
|
arr = json.loads(ret)
|
||||||
|
|
||||||
|
if options.list:
|
||||||
|
return arr
|
||||||
|
|
||||||
|
# Fix for NCPA < 2
|
||||||
|
if 'value' in arr:
|
||||||
|
arr = arr['value']
|
||||||
|
|
||||||
|
# We need to flip the returncode and stdout
|
||||||
|
if isinstance(arr['stdout'], int) and not isinstance(arr['returncode'], int):
|
||||||
|
tmp = arr['returncode']
|
||||||
|
arr['returncode'] = arr['stdout']
|
||||||
|
arr['stdout'] = tmp
|
||||||
|
|
||||||
|
# If we recieve and error, return critical and give out error text
|
||||||
|
elif 'error' in arr:
|
||||||
|
arr['stdout'] = 'CRITICAL: %s' % arr['error']
|
||||||
|
arr['returncode'] = 2
|
||||||
|
|
||||||
|
return arr
|
||||||
|
|
||||||
|
|
||||||
|
def run_check(info_json):
|
||||||
|
"""Run a check against the remote host.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'stdout' in info_json and 'returncode' in info_json:
|
||||||
|
return info_json['stdout'], info_json['returncode']
|
||||||
|
elif 'error' in info_json:
|
||||||
|
return info_json['error'], 3
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
stdout = "{0} | 'status'={1};1;2;;".format(stdout, returncode)
|
||||||
|
return stdout, returncode
|
||||||
|
except (HTTPError, URLError) as e:
|
||||||
|
if options.debug:
|
||||||
|
return 'The stack trace:\n' + traceback.format_exc(), 3
|
||||||
|
elif options.verbose:
|
||||||
|
return 'An error occurred:\n' + str(e.error_message), 3
|
||||||
|
else:
|
||||||
|
return e.error_message, 3
|
||||||
|
except Exception as e:
|
||||||
|
if options.debug:
|
||||||
|
return 'The stack trace:\n' + traceback.format_exc(), 3
|
||||||
|
elif options.verbose:
|
||||||
|
return 'An error occurred:\n' + 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()
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
print(unicode(stdout).encode('utf-8'))
|
||||||
|
else:
|
||||||
|
print(stdout.encode().decode('utf-8'))
|
||||||
|
sys.exit(returncode)
|
||||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user