mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-02-20 00:10:09 -05:00
Merge branch 'master' into refactor/check_load
This commit is contained in:
commit
92c7b91002
52 changed files with 5290 additions and 5170 deletions
|
|
@ -4,7 +4,7 @@ TabWidth: 4
|
|||
AllowShortIfStatementsOnASingleLine: false
|
||||
BreakBeforeBraces: Attach
|
||||
AlignConsecutiveMacros: true
|
||||
ColumnLimit: 140
|
||||
ColumnLimit: 100
|
||||
IndentPPDirectives: AfterHash
|
||||
SortIncludes: Never
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
|
|
|
|||
14
.github/monitoring-plugins.spec
vendored
14
.github/monitoring-plugins.spec
vendored
|
|
@ -191,7 +191,6 @@ Requires: %{name}-nt
|
|||
Requires: %{name}-ntp
|
||||
Requires: %{name}-ntp_peer
|
||||
Requires: %{name}-ntp_time
|
||||
Requires: %{name}-nwstat
|
||||
Requires: %{name}-oracle
|
||||
Requires: %{name}-pgsql
|
||||
Requires: %{name}-ping
|
||||
|
|
@ -702,19 +701,6 @@ Provides check_ntp_time of the Monitoring Plugins.
|
|||
|
||||
|
||||
|
||||
# check_nwstat
|
||||
%package nwstat
|
||||
Summary: Monitoring Plugins - check_nwstat
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description nwstat
|
||||
Provides check_nwstat of the Monitoring Plugins.
|
||||
|
||||
%files nwstat
|
||||
%{plugindir}/check_nwstat
|
||||
|
||||
|
||||
|
||||
# check_oracle
|
||||
%package oracle
|
||||
Summary: Monitoring Plugins - check_oracle
|
||||
|
|
|
|||
7
.github/os_detect.sh
vendored
7
.github/os_detect.sh
vendored
|
|
@ -1,10 +1,17 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
. /etc/os-release
|
||||
|
||||
# workaround for really bare-bones Archlinux containers:
|
||||
if [ -x "$(command -v pacman)" ]; then
|
||||
pacman --noconfirm -Sy
|
||||
pacman --noconfirm -S grep gawk sed
|
||||
fi
|
||||
|
||||
if [ ${ID} == "fedora" -a ${VERSION_ID} -gt 41 ]; then
|
||||
dnf install -y gawk
|
||||
fi
|
||||
|
||||
os_release_file=
|
||||
if [ -s "/etc/os-release" ]; then
|
||||
os_release_file="/etc/os-release"
|
||||
|
|
|
|||
2
.github/workflows/test-next.yml
vendored
2
.github/workflows/test-next.yml
vendored
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
${{ matrix.distro }} \
|
||||
/bin/sh -c '${{ matrix.prepare }} && \
|
||||
tools/setup && \
|
||||
./configure --enable-libtap --with-ipv6=no && \
|
||||
./configure --enable-libtap && \
|
||||
make && \
|
||||
make test && \
|
||||
make dist && \
|
||||
|
|
|
|||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
|
@ -35,7 +35,7 @@ jobs:
|
|||
${{ matrix.distro }} \
|
||||
/bin/sh -c '${{ matrix.prepare }} && \
|
||||
tools/setup && \
|
||||
./configure --enable-libtap --with-ipv6=no && \
|
||||
./configure --enable-libtap && \
|
||||
make && \
|
||||
make test && \
|
||||
make dist && \
|
||||
|
|
|
|||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -114,7 +114,6 @@ NP-VERSION-FILE
|
|||
/lib/tests/Makefile.in
|
||||
/lib/tests/test_base64
|
||||
/lib/tests/test_cmd
|
||||
/lib/tests/test_disk
|
||||
/lib/tests/test_tcp
|
||||
/lib/tests/test_utils
|
||||
/lib/tests/utils_base.Po
|
||||
|
|
@ -153,6 +152,8 @@ NP-VERSION-FILE
|
|||
/plugins/check_dbi
|
||||
/plugins/check_dig
|
||||
/plugins/check_disk
|
||||
plugins/check_disk.d/.deps/
|
||||
plugins/check_disk.d/.dirstamp
|
||||
/plugins/check_dns
|
||||
/plugins/check_dummy
|
||||
/plugins/check_fping
|
||||
|
|
@ -177,7 +178,6 @@ NP-VERSION-FILE
|
|||
/plugins/check_ntp
|
||||
/plugins/check_ntp_peer
|
||||
/plugins/check_ntp_time
|
||||
/plugins/check_nwstat
|
||||
/plugins/check_pgsql
|
||||
/plugins/check_ping
|
||||
/plugins/check_pop
|
||||
|
|
@ -222,7 +222,7 @@ NP-VERSION-FILE
|
|||
/plugins/tests/Makefile
|
||||
/plugins/tests/Makefile.in
|
||||
/plugins/tests/test_utils
|
||||
/plugins/tests/test_disk
|
||||
/plugins/tests/test_check_disk
|
||||
/plugins/tests/test_check_swap
|
||||
/plugins/tests/.deps
|
||||
/plugins/tests/.dirstamp
|
||||
|
|
|
|||
|
|
@ -87,10 +87,6 @@ check_ifstatus/check_ifoperstatus
|
|||
- Requires Net::SNMP perl module
|
||||
http://www.perl.com/CPAN/modules/by-authors/id/D/DT/DTOWN/
|
||||
|
||||
check_nwstat:
|
||||
- Requires MRTGEXT NLM for Novell Servers
|
||||
http://forge.novell.com/modules/xfmod/project/?mrtgext
|
||||
|
||||
check_nt:
|
||||
- Requires NSClient to run on the NT server to monitor
|
||||
http://nsclient.ready2run.nl/
|
||||
|
|
|
|||
50
configure.ac
50
configure.ac
|
|
@ -181,10 +181,10 @@ fi
|
|||
|
||||
# Finally, define tests if we use libtap
|
||||
if test "$enable_libtap" = "yes" ; then
|
||||
EXTRA_TEST="test_utils test_disk test_tcp test_cmd test_base64"
|
||||
EXTRA_TEST="test_utils test_tcp test_cmd test_base64"
|
||||
AC_SUBST(EXTRA_TEST)
|
||||
|
||||
EXTRA_PLUGIN_TESTS="tests/test_check_swap"
|
||||
EXTRA_PLUGIN_TESTS="tests/test_check_swap tests/test_check_disk"
|
||||
AC_SUBST(EXTRA_PLUGIN_TESTS)
|
||||
fi
|
||||
|
||||
|
|
@ -796,7 +796,7 @@ elif ps axwo 'stat comm vsz rss user uid pid ppid etime args' 2>/dev/null | \
|
|||
then
|
||||
ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,procetime,procprog,&pos]"
|
||||
ac_cv_ps_command="$PATH_TO_PS axwo 'stat uid pid ppid vsz rss pcpu etime comm args'"
|
||||
ac_cv_ps_format="%s %d %d %d %d %d %f %s %s %n"
|
||||
ac_cv_ps_format="%s %u %d %d %d %d %f %s %s %n"
|
||||
ac_cv_ps_cols=10
|
||||
AC_MSG_RESULT([$ac_cv_ps_command])
|
||||
|
||||
|
|
@ -1519,21 +1519,47 @@ then
|
|||
fi
|
||||
|
||||
AC_PATH_PROG(PATH_TO_FPING,fping)
|
||||
AC_PATH_PROG(PATH_TO_FPING6,fping6)
|
||||
|
||||
AC_ARG_WITH(fping_command,
|
||||
ACX_HELP_STRING([--with-fping-command=PATH],
|
||||
[Path to fping command]), PATH_TO_FPING=$withval)
|
||||
AC_ARG_WITH(fping6_command,
|
||||
ACX_HELP_STRING([--with-fping6-command=PATH],
|
||||
[Path to fping6 command]), PATH_TO_FPING6=$withval)
|
||||
|
||||
if test -n "$PATH_TO_FPING"
|
||||
then
|
||||
if test -n "$PATH_TO_FPING"; then
|
||||
AC_DEFINE_UNQUOTED(PATH_TO_FPING,"$PATH_TO_FPING",[path to fping])
|
||||
EXTRAS="$EXTRAS check_fping\$(EXEEXT)"
|
||||
if test x"$with_ipv6" != xno && test -n "$PATH_TO_FPING6"; then
|
||||
AC_DEFINE_UNQUOTED(PATH_TO_FPING6,"$PATH_TO_FPING6",[path to fping6])
|
||||
|
||||
if test -z "$($PATH_TO_FPING --version)" ; then
|
||||
AC_MSG_NOTICE([failed to get version of fping])
|
||||
else
|
||||
FPING_MAJOR_VERSION="$($PATH_TO_FPING --version | sed 's/.*fping: Version //' | sed 's/\..*//')"
|
||||
FPING_MINOR_VERSION="$($PATH_TO_FPING --version | sed 's/.*fping: Version //' | sed 's/.*\.//')"
|
||||
|
||||
if test $FPING_MAJOR_VERSION -eq 5 ; then
|
||||
if test $FPING_MINOR_VERSION -ge 3 ; then
|
||||
AC_DEFINE(FPING_VERSION_5_3_OR_HIGHER, "true", [fping is of version 5.3 or higher])
|
||||
AC_MSG_NOTICE([fping is of version 5.3 or higher])
|
||||
AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
|
||||
AC_MSG_NOTICE([fping is of version 5.2 or higher])
|
||||
elif test $FPING_MINOR_VERSION -ge 2 ; then
|
||||
AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
|
||||
AC_MSG_NOTICE([fping is of version 5.2 or higher])
|
||||
else
|
||||
AC_MSG_NOTICE([fping is of a version lower then 5.2])
|
||||
fi
|
||||
|
||||
elif $FPING_MAJOR_VERSION > 5 ; then
|
||||
AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
|
||||
AC_MSG_NOTICE([fping is of version 5.2 or higher])
|
||||
AC_DEFINE(FPING_VERSION_5_3_OR_HIGHER, "true", [fping is of version 5.2 or higher])
|
||||
AC_MSG_NOTICE([fping is of version 5.3 or higher])
|
||||
fi
|
||||
|
||||
if test "`fping --version | sed 's/.*fping: Version //'`" = "5.2" ; then
|
||||
AC_DEFINE(FPING_VERSION, "5.2", [the version of fping available])
|
||||
AC_MSG_NOTICE([fping version: 5.2])
|
||||
elif test "`fping --version | sed 's/.*fping: Version //'`" = "5.3"; then
|
||||
AC_DEFINE(FPING_VERSION, "5.3", [the version of fping available])
|
||||
AC_MSG_NOTICE([fping version: 5.3])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([Get fping from http://www.fping.com in order to make check_fping plugin])
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ noinst_LIBRARIES = libmonitoringplug.a
|
|||
AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \
|
||||
-I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins
|
||||
|
||||
libmonitoringplug_a_SOURCES = utils_base.c utils_disk.c utils_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c
|
||||
libmonitoringplug_a_SOURCES = utils_base.c utils_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c
|
||||
|
||||
EXTRA_DIST = utils_base.h \
|
||||
utils_disk.h \
|
||||
utils_tcp.h \
|
||||
utils_cmd.h \
|
||||
parse_ini.h \
|
||||
|
|
|
|||
91
lib/output.c
91
lib/output.c
|
|
@ -13,9 +13,11 @@
|
|||
|
||||
// == Global variables
|
||||
static mp_output_format output_format = MP_FORMAT_DEFAULT;
|
||||
static mp_output_detail_level level_of_detail = MP_DETAIL_ALL;
|
||||
|
||||
// == Prototypes ==
|
||||
static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation);
|
||||
static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
|
||||
unsigned int indentation);
|
||||
static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
|
||||
|
||||
// == Implementation ==
|
||||
|
|
@ -57,7 +59,9 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
|
|||
* It sets useful defaults
|
||||
*/
|
||||
mp_check mp_check_init(void) {
|
||||
mp_check check = {0};
|
||||
mp_check check = {
|
||||
.evaluation_function = &mp_eval_check_default,
|
||||
};
|
||||
return check;
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +124,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata
|
|||
*/
|
||||
int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) {
|
||||
if (subcheck.output == NULL) {
|
||||
die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL");
|
||||
die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__,
|
||||
"Sub check output is NULL");
|
||||
}
|
||||
|
||||
mp_subcheck_list *tmp = NULL;
|
||||
|
|
@ -193,16 +198,33 @@ char *get_subcheck_summary(mp_check check) {
|
|||
return result;
|
||||
}
|
||||
|
||||
mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) {
|
||||
if (subcheck.evaluation_function == NULL) {
|
||||
return mp_eval_subcheck_default(subcheck);
|
||||
}
|
||||
return subcheck.evaluation_function(subcheck);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states
|
||||
* Generate the result state of a mp_subcheck object based on its own state and its subchecks
|
||||
* states
|
||||
*/
|
||||
mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
|
||||
if (check.state_set_explicitly) {
|
||||
return check.state;
|
||||
mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) {
|
||||
if (subcheck.evaluation_function != NULL) {
|
||||
return subcheck.evaluation_function(subcheck);
|
||||
}
|
||||
|
||||
mp_subcheck_list *scl = check.subchecks;
|
||||
mp_state_enum result = check.default_state;
|
||||
if (subcheck.state_set_explicitly) {
|
||||
return subcheck.state;
|
||||
}
|
||||
|
||||
mp_subcheck_list *scl = subcheck.subchecks;
|
||||
|
||||
if (scl == NULL) {
|
||||
return subcheck.default_state;
|
||||
}
|
||||
|
||||
mp_state_enum result = STATE_OK;
|
||||
|
||||
while (scl != NULL) {
|
||||
result = max_state_alt(result, mp_compute_subcheck_state(scl->subcheck));
|
||||
|
|
@ -212,10 +234,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
|
|||
return result;
|
||||
}
|
||||
|
||||
mp_state_enum mp_compute_check_state(const mp_check check) {
|
||||
// just a safety check
|
||||
if (check.evaluation_function == NULL) {
|
||||
return mp_eval_check_default(check);
|
||||
}
|
||||
return check.evaluation_function(check);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the result state of a mp_check object based on it's own state and it's subchecks states
|
||||
*/
|
||||
mp_state_enum mp_compute_check_state(const mp_check check) {
|
||||
mp_state_enum mp_eval_check_default(const mp_check check) {
|
||||
assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here
|
||||
|
||||
mp_subcheck_list *scl = check.subchecks;
|
||||
|
|
@ -247,7 +277,11 @@ char *mp_fmt_output(mp_check check) {
|
|||
mp_subcheck_list *subchecks = check.subchecks;
|
||||
|
||||
while (subchecks != NULL) {
|
||||
asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
|
||||
if (level_of_detail == MP_DETAIL_ALL ||
|
||||
mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
|
||||
asprintf(&result, "%s\n%s", result,
|
||||
fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
|
||||
}
|
||||
subchecks = subchecks->next;
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +292,8 @@ char *mp_fmt_output(mp_check check) {
|
|||
if (pd_string == NULL) {
|
||||
asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck));
|
||||
} else {
|
||||
asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck));
|
||||
asprintf(&pd_string, "%s %s", pd_string,
|
||||
fmt_subcheck_perfdata(subchecks->subcheck));
|
||||
}
|
||||
|
||||
subchecks = subchecks->next;
|
||||
|
|
@ -327,7 +362,8 @@ static char *generate_indentation_string(unsigned int indentation) {
|
|||
/*
|
||||
* Helper function to generate the output string of mp_subcheck
|
||||
*/
|
||||
static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) {
|
||||
static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
|
||||
unsigned int indentation) {
|
||||
char *result = NULL;
|
||||
mp_subcheck_list *subchecks = NULL;
|
||||
|
||||
|
|
@ -341,7 +377,7 @@ static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subch
|
|||
|
||||
while (tmp_string != NULL) {
|
||||
*tmp_string = '\0';
|
||||
xasprintf(&intermediate_string, "%s%s\n%s", intermediate_string,check.output, generate_indentation_string(indentation+1)); // one more indentation to make it look better
|
||||
asprintf(&intermediate_string, "%s%s\n%s", intermediate_string,check.output, generate_indentation_string(indentation+1)); // one more indentation to make it look better
|
||||
|
||||
if (*(tmp_string + 1) != '\0') {
|
||||
check.output = tmp_string + 1;
|
||||
|
|
@ -369,7 +405,8 @@ static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subch
|
|||
subchecks = check.subchecks;
|
||||
|
||||
while (subchecks != NULL) {
|
||||
asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
|
||||
asprintf(&result, "%s\n%s", result,
|
||||
fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
|
||||
subchecks = subchecks->next;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -570,3 +607,27 @@ parsed_output_format mp_parse_output_format(char *format_string) {
|
|||
void mp_set_format(mp_output_format format) { output_format = format; }
|
||||
|
||||
mp_output_format mp_get_format(void) { return output_format; }
|
||||
|
||||
void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; }
|
||||
|
||||
mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; }
|
||||
|
||||
mp_state_enum mp_eval_ok(mp_check overall) {
|
||||
(void)overall;
|
||||
return STATE_OK;
|
||||
}
|
||||
|
||||
mp_state_enum mp_eval_warning(mp_check overall) {
|
||||
(void)overall;
|
||||
return STATE_WARNING;
|
||||
}
|
||||
|
||||
mp_state_enum mp_eval_critical(mp_check overall) {
|
||||
(void)overall;
|
||||
return STATE_CRITICAL;
|
||||
}
|
||||
|
||||
mp_state_enum mp_eval_unknown(mp_check overall) {
|
||||
(void)overall;
|
||||
return STATE_UNKNOWN;
|
||||
}
|
||||
|
|
|
|||
47
lib/output.h
47
lib/output.h
|
|
@ -7,15 +7,21 @@
|
|||
/*
|
||||
* A partial check result
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct mp_subcheck mp_subcheck;
|
||||
struct mp_subcheck {
|
||||
mp_state_enum state; // OK, Warning, Critical ... set explicitly
|
||||
mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly
|
||||
bool state_set_explicitly; // was the state set explicitly (or should it be derived from subchecks)
|
||||
bool state_set_explicitly; // was the state set explicitly (or should it be derived from
|
||||
// subchecks)
|
||||
|
||||
char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP connection to..")
|
||||
pd_list *perfdata; // Performance data for this check
|
||||
char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP
|
||||
// connection to..")
|
||||
pd_list *perfdata; // Performance data for this check
|
||||
struct subcheck_list *subchecks; // subchecks deeper in the hierarchy
|
||||
} mp_subcheck;
|
||||
|
||||
// the evaluation_functions computes the state of subcheck
|
||||
mp_state_enum (*evaluation_function)(mp_subcheck);
|
||||
};
|
||||
|
||||
/*
|
||||
* A list of subchecks, used in subchecks and the main check
|
||||
|
|
@ -38,8 +44,18 @@ typedef enum output_format {
|
|||
/*
|
||||
* Format related functions
|
||||
*/
|
||||
void mp_set_format(mp_output_format format);
|
||||
mp_output_format mp_get_format(void);
|
||||
void mp_set_format(mp_output_format format);
|
||||
mp_output_format mp_get_format(void);
|
||||
|
||||
// Output detail level
|
||||
|
||||
typedef enum output_detail_level {
|
||||
MP_DETAIL_ALL,
|
||||
MP_DETAIL_NON_OK_ONLY,
|
||||
} mp_output_detail_level;
|
||||
|
||||
void mp_set_level_of_detail(mp_output_detail_level level);
|
||||
mp_output_detail_level mp_get_level_of_detail(void);
|
||||
|
||||
/*
|
||||
* The main state object of a plugin. Exists only ONCE per plugin.
|
||||
|
|
@ -47,10 +63,14 @@ typedef enum output_format {
|
|||
* The final result is always derived from the children and the "worst" state
|
||||
* in the first layer of subchecks
|
||||
*/
|
||||
typedef struct {
|
||||
char *summary; // Overall summary, if not set a summary will be automatically generated
|
||||
typedef struct mp_check mp_check;
|
||||
struct mp_check {
|
||||
char *summary; // Overall summary, if not set a summary will be automatically generated
|
||||
mp_subcheck_list *subchecks;
|
||||
} mp_check;
|
||||
|
||||
// the evaluation_functions computes the state of check
|
||||
mp_state_enum (*evaluation_function)(mp_check);
|
||||
};
|
||||
|
||||
mp_check mp_check_init(void);
|
||||
mp_subcheck mp_subcheck_init(void);
|
||||
|
|
@ -68,6 +88,13 @@ void mp_add_summary(mp_check check[static 1], char *summary);
|
|||
mp_state_enum mp_compute_check_state(mp_check);
|
||||
mp_state_enum mp_compute_subcheck_state(mp_subcheck);
|
||||
|
||||
mp_state_enum mp_eval_ok(mp_check overall);
|
||||
mp_state_enum mp_eval_warning(mp_check overall);
|
||||
mp_state_enum mp_eval_critical(mp_check overall);
|
||||
mp_state_enum mp_eval_unknown(mp_check overall);
|
||||
mp_state_enum mp_eval_check_default(mp_check check);
|
||||
mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck);
|
||||
|
||||
typedef struct {
|
||||
bool parsing_success;
|
||||
mp_output_format output_format;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ char *pd_value_to_string(const mp_perfdata_value pd) {
|
|||
char *pd_to_string(mp_perfdata pd) {
|
||||
assert(pd.label != NULL);
|
||||
char *result = NULL;
|
||||
asprintf(&result, "%s=", pd.label);
|
||||
asprintf(&result, "'%s'=", pd.label);
|
||||
|
||||
asprintf(&result, "%s%s", result, pd_value_to_string(pd.value));
|
||||
|
||||
|
|
@ -257,6 +257,10 @@ mp_perfdata mp_set_pd_value_double(mp_perfdata pd, double value) {
|
|||
return pd;
|
||||
}
|
||||
|
||||
mp_perfdata mp_set_pd_value_char(mp_perfdata pd, char value) { return mp_set_pd_value_long_long(pd, (long long)value); }
|
||||
|
||||
mp_perfdata mp_set_pd_value_u_char(mp_perfdata pd, unsigned char value) { return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); }
|
||||
|
||||
mp_perfdata mp_set_pd_value_int(mp_perfdata pd, int value) { return mp_set_pd_value_long_long(pd, (long long)value); }
|
||||
|
||||
mp_perfdata mp_set_pd_value_u_int(mp_perfdata pd, unsigned int value) { return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); }
|
||||
|
|
@ -288,6 +292,10 @@ mp_perfdata_value mp_create_pd_value_double(double value) {
|
|||
|
||||
mp_perfdata_value mp_create_pd_value_float(float value) { return mp_create_pd_value_double((double)value); }
|
||||
|
||||
mp_perfdata_value mp_create_pd_value_char(char value) { return mp_create_pd_value_long_long((long long)value); }
|
||||
|
||||
mp_perfdata_value mp_create_pd_value_u_char(unsigned char value) { return mp_create_pd_value_u_long_long((unsigned long long)value); }
|
||||
|
||||
mp_perfdata_value mp_create_pd_value_int(int value) { return mp_create_pd_value_long_long((long long)value); }
|
||||
|
||||
mp_perfdata_value mp_create_pd_value_u_int(unsigned int value) { return mp_create_pd_value_u_long_long((unsigned long long)value); }
|
||||
|
|
@ -514,3 +522,84 @@ perfdata_value_parser_wrapper parse_pd_value(const char *input) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
mp_perfdata mp_set_pd_max_value(mp_perfdata perfdata, mp_perfdata_value value) {
|
||||
perfdata.max = value;
|
||||
perfdata.max_present = true;
|
||||
return perfdata;
|
||||
}
|
||||
|
||||
mp_perfdata mp_set_pd_min_value(mp_perfdata perfdata, mp_perfdata_value value) {
|
||||
perfdata.min = value;
|
||||
perfdata.min_present = true;
|
||||
return perfdata;
|
||||
}
|
||||
|
||||
double mp_get_pd_value(mp_perfdata_value value) {
|
||||
assert(value.type != PD_TYPE_NONE);
|
||||
switch (value.type) {
|
||||
case PD_TYPE_DOUBLE:
|
||||
return value.pd_double;
|
||||
case PD_TYPE_INT:
|
||||
return (double)value.pd_int;
|
||||
case PD_TYPE_UINT:
|
||||
return (double)value.pd_uint;
|
||||
default:
|
||||
return 0; // just to make the compiler happy
|
||||
}
|
||||
}
|
||||
|
||||
mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value right) {
|
||||
if (left.type == right.type) {
|
||||
switch (left.type) {
|
||||
case PD_TYPE_DOUBLE:
|
||||
left.pd_double *= right.pd_double;
|
||||
return left;
|
||||
case PD_TYPE_INT:
|
||||
left.pd_int *= right.pd_int;
|
||||
return left;
|
||||
case PD_TYPE_UINT:
|
||||
left.pd_uint *= right.pd_uint;
|
||||
return left;
|
||||
default:
|
||||
// what to here?
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
// Different types, oh boy, just do the lazy thing for now and switch to double
|
||||
switch (left.type) {
|
||||
case PD_TYPE_INT:
|
||||
left.pd_double = (double)left.pd_int;
|
||||
left.type = PD_TYPE_DOUBLE;
|
||||
break;
|
||||
case PD_TYPE_UINT:
|
||||
left.pd_double = (double)left.pd_uint;
|
||||
left.type = PD_TYPE_DOUBLE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (right.type) {
|
||||
case PD_TYPE_INT:
|
||||
right.pd_double = (double)right.pd_int;
|
||||
right.type = PD_TYPE_DOUBLE;
|
||||
break;
|
||||
case PD_TYPE_UINT:
|
||||
right.pd_double = (double)right.pd_uint;
|
||||
right.type = PD_TYPE_DOUBLE;
|
||||
break;
|
||||
}
|
||||
|
||||
left.pd_double *= right.pd_double;
|
||||
return left;
|
||||
}
|
||||
|
||||
mp_range mp_range_multiply(mp_range range, mp_perfdata_value factor) {
|
||||
if (!range.end_infinity) {
|
||||
range.end = mp_pd_value_multiply(range.end, factor);
|
||||
}
|
||||
if (!range.start_infinity) {
|
||||
range.start = mp_pd_value_multiply(range.start, factor);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long);
|
|||
_Generic((V), \
|
||||
float: mp_create_pd_value_float, \
|
||||
double: mp_create_pd_value_double, \
|
||||
char: mp_create_pd_value_char, \
|
||||
unsigned char: mp_create_pd_value_u_char, \
|
||||
int: mp_create_pd_value_int, \
|
||||
unsigned int: mp_create_pd_value_u_int, \
|
||||
long: mp_create_pd_value_long, \
|
||||
|
|
@ -164,6 +166,8 @@ mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long);
|
|||
|
||||
mp_perfdata_value mp_create_pd_value_float(float);
|
||||
mp_perfdata_value mp_create_pd_value_double(double);
|
||||
mp_perfdata_value mp_create_pd_value_char(char);
|
||||
mp_perfdata_value mp_create_pd_value_u_char(unsigned char);
|
||||
mp_perfdata_value mp_create_pd_value_int(int);
|
||||
mp_perfdata_value mp_create_pd_value_u_int(unsigned int);
|
||||
mp_perfdata_value mp_create_pd_value_long(long);
|
||||
|
|
@ -171,6 +175,11 @@ mp_perfdata_value mp_create_pd_value_u_long(unsigned long);
|
|||
mp_perfdata_value mp_create_pd_value_long_long(long long);
|
||||
mp_perfdata_value mp_create_pd_value_u_long_long(unsigned long long);
|
||||
|
||||
mp_perfdata mp_set_pd_max_value(mp_perfdata perfdata, mp_perfdata_value value);
|
||||
mp_perfdata mp_set_pd_min_value(mp_perfdata perfdata, mp_perfdata_value value);
|
||||
|
||||
double mp_get_pd_value(mp_perfdata_value value);
|
||||
|
||||
/*
|
||||
* Free the memory used by a pd_list
|
||||
*/
|
||||
|
|
@ -178,6 +187,13 @@ void pd_list_free(pd_list[1]);
|
|||
|
||||
int cmp_perfdata_value(mp_perfdata_value, mp_perfdata_value);
|
||||
|
||||
// ================
|
||||
// Helper functions
|
||||
// ================
|
||||
|
||||
mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value right);
|
||||
mp_range mp_range_multiply(mp_range range, mp_perfdata_value factor);
|
||||
|
||||
// =================
|
||||
// String formatters
|
||||
// =================
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ check_PROGRAMS = @EXTRA_TEST@
|
|||
AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \
|
||||
-I$(top_srcdir)/lib -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins
|
||||
|
||||
EXTRA_PROGRAMS = test_utils test_disk test_tcp test_cmd test_base64 test_ini1 test_ini3 test_opts1 test_opts2 test_opts3 test_generic_output
|
||||
EXTRA_PROGRAMS = test_utils test_tcp test_cmd test_base64 test_ini1 test_ini3 test_opts1 test_opts2 test_opts3 test_generic_output
|
||||
|
||||
np_test_scripts = test_base64.t test_cmd.t test_disk.t test_ini1.t test_ini3.t test_opts1.t test_opts2.t test_opts3.t test_tcp.t test_utils.t test_generic_output.t
|
||||
np_test_scripts = test_base64.t test_cmd.t test_ini1.t test_ini3.t test_opts1.t test_opts2.t test_opts3.t test_tcp.t test_utils.t test_generic_output.t
|
||||
np_test_files = config-dos.ini config-opts.ini config-tiny.ini plugin.ini plugins.ini
|
||||
EXTRA_DIST = $(np_test_scripts) $(np_test_files) var
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ AM_CFLAGS = -g -I$(top_srcdir)/lib -I$(top_srcdir)/gl $(tap_cflags)
|
|||
AM_LDFLAGS = $(tap_ldflags) -ltap
|
||||
LDADD = $(top_srcdir)/lib/libmonitoringplug.a $(top_srcdir)/gl/libgnu.a $(LIB_CRYPTO)
|
||||
|
||||
SOURCES = test_utils.c test_disk.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c test_generic_output.c
|
||||
SOURCES = test_utils.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c test_generic_output.c
|
||||
|
||||
test: ${noinst_PROGRAMS}
|
||||
perl -MTest::Harness -e '$$Test::Harness::switches=""; runtests(map {$$_ .= ".t"} @ARGV)' $(EXTRA_PROGRAMS)
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
use Test::More;
|
||||
if (! -e "./test_disk") {
|
||||
plan skip_all => "./test_disk not compiled - please enable libtap library to test";
|
||||
}
|
||||
exec "./test_disk";
|
||||
|
|
@ -51,9 +51,21 @@ mp_state_enum mp_get_pd_status(mp_perfdata perfdata) {
|
|||
}
|
||||
if (perfdata.warn_present) {
|
||||
if (mp_check_range(perfdata.value, perfdata.warn)) {
|
||||
return STATE_CRITICAL;
|
||||
return STATE_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
return STATE_OK;
|
||||
}
|
||||
|
||||
mp_thresholds mp_thresholds_set_warn(mp_thresholds thlds, mp_range warn) {
|
||||
thlds.warning = warn;
|
||||
thlds.warning_is_set = true;
|
||||
return thlds;
|
||||
}
|
||||
|
||||
mp_thresholds mp_thresholds_set_crit(mp_thresholds thlds, mp_range crit) {
|
||||
thlds.critical = crit;
|
||||
thlds.critical_is_set = true;
|
||||
return thlds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,5 +24,8 @@ mp_perfdata mp_pd_set_thresholds(mp_perfdata /* pd */, mp_thresholds /* th */);
|
|||
|
||||
mp_state_enum mp_get_pd_status(mp_perfdata /* pd */);
|
||||
|
||||
mp_thresholds mp_thresholds_set_warn(mp_thresholds thlds, mp_range warn);
|
||||
mp_thresholds mp_thresholds_set_crit(mp_thresholds thlds, mp_range crit);
|
||||
|
||||
char *fmt_threshold_warning(thresholds th);
|
||||
char *fmt_threshold_critical(thresholds th);
|
||||
|
|
|
|||
|
|
@ -225,27 +225,15 @@ bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
|
|||
if (my_range.end_infinity == false && my_range.start_infinity == false) {
|
||||
// range: .........|---inside---|...........
|
||||
// value
|
||||
if ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0)) {
|
||||
is_inside = true;
|
||||
} else {
|
||||
is_inside = false;
|
||||
}
|
||||
is_inside = ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0));
|
||||
} else if (my_range.start_infinity == false && my_range.end_infinity == true) {
|
||||
// range: .........|---inside---------
|
||||
// value
|
||||
if (cmp_perfdata_value(my_range.start, value) < 0) {
|
||||
is_inside = true;
|
||||
} else {
|
||||
is_inside = false;
|
||||
}
|
||||
is_inside = (cmp_perfdata_value(my_range.start, value) < 0);
|
||||
} else if (my_range.start_infinity == true && my_range.end_infinity == false) {
|
||||
// range: -inside--------|....................
|
||||
// value
|
||||
if (cmp_perfdata_value(value, my_range.end) == -1) {
|
||||
is_inside = true;
|
||||
} else {
|
||||
is_inside = false;
|
||||
}
|
||||
is_inside = (cmp_perfdata_value(value, my_range.end) == -1);
|
||||
} else {
|
||||
// range from -inf to inf, so always inside
|
||||
is_inside = true;
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ int cmd_run_array(char *const *argv, output *out, output *err, int flags) {
|
|||
return _cmd_close(fd);
|
||||
}
|
||||
|
||||
int cmd_file_read(char *filename, output *out, int flags) {
|
||||
int cmd_file_read(const char *filename, output *out, int flags) {
|
||||
int fd;
|
||||
if (out)
|
||||
memset(out, 0, sizeof(output));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ typedef struct output output;
|
|||
/** prototypes **/
|
||||
int cmd_run(const char *, output *, output *, int);
|
||||
int cmd_run_array(char *const *, output *, output *, int);
|
||||
int cmd_file_read(char *, output *, int);
|
||||
int cmd_file_read(const char *, output *, int);
|
||||
|
||||
/* only multi-threaded plugins need to bother with this */
|
||||
void cmd_init(void);
|
||||
|
|
|
|||
255
lib/utils_disk.c
255
lib/utils_disk.c
|
|
@ -1,255 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* Library for check_disk
|
||||
*
|
||||
* License: GPL
|
||||
* Copyright (c) 1999-2024 Monitoring Plugins Development Team
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This file contains utilities for check_disk. These are tested by libtap
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "utils_disk.h"
|
||||
#include "gl/fsusage.h"
|
||||
#include <string.h>
|
||||
|
||||
void np_add_name(struct name_list **list, const char *name) {
|
||||
struct name_list *new_entry;
|
||||
new_entry = (struct name_list *)malloc(sizeof *new_entry);
|
||||
new_entry->name = (char *)name;
|
||||
new_entry->next = *list;
|
||||
*list = new_entry;
|
||||
}
|
||||
|
||||
/* @brief Initialises a new regex at the begin of list via regcomp(3)
|
||||
*
|
||||
* @details if the regex fails to compile the error code of regcomp(3) is returned
|
||||
* and list is not modified, otherwise list is modified to point to the new
|
||||
* element
|
||||
* @param list Pointer to a linked list of regex_list elements
|
||||
* @param regex the string containing the regex which should be inserted into the list
|
||||
* @param clags the cflags parameter for regcomp(3)
|
||||
*/
|
||||
int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
|
||||
struct regex_list *new_entry = (struct regex_list *)malloc(sizeof *new_entry);
|
||||
|
||||
if (new_entry == NULL) {
|
||||
die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
|
||||
}
|
||||
|
||||
int regcomp_result = regcomp(&new_entry->regex, regex, cflags);
|
||||
|
||||
if (!regcomp_result) {
|
||||
// regcomp succeeded
|
||||
new_entry->next = *list;
|
||||
*list = new_entry;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
// regcomp failed
|
||||
free(new_entry);
|
||||
|
||||
return regcomp_result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialises a new parameter at the end of list */
|
||||
struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name) {
|
||||
struct parameter_list *current = *list;
|
||||
struct parameter_list *new_path;
|
||||
new_path = (struct parameter_list *)malloc(sizeof *new_path);
|
||||
new_path->name = (char *)malloc(strlen(name) + 1);
|
||||
new_path->best_match = NULL;
|
||||
new_path->name_next = NULL;
|
||||
new_path->name_prev = NULL;
|
||||
new_path->freespace_bytes = NULL;
|
||||
new_path->freespace_units = NULL;
|
||||
new_path->freespace_percent = NULL;
|
||||
new_path->usedspace_bytes = NULL;
|
||||
new_path->usedspace_units = NULL;
|
||||
new_path->usedspace_percent = NULL;
|
||||
new_path->usedinodes_percent = NULL;
|
||||
new_path->freeinodes_percent = NULL;
|
||||
new_path->group = NULL;
|
||||
new_path->dfree_pct = -1;
|
||||
new_path->dused_pct = -1;
|
||||
new_path->total = 0;
|
||||
new_path->available = 0;
|
||||
new_path->available_to_root = 0;
|
||||
new_path->used = 0;
|
||||
new_path->dused_units = 0;
|
||||
new_path->dfree_units = 0;
|
||||
new_path->dtotal_units = 0;
|
||||
new_path->inodes_total = 0;
|
||||
new_path->inodes_free = 0;
|
||||
new_path->inodes_free_to_root = 0;
|
||||
new_path->inodes_used = 0;
|
||||
new_path->dused_inodes_percent = 0;
|
||||
new_path->dfree_inodes_percent = 0;
|
||||
|
||||
strcpy(new_path->name, name);
|
||||
|
||||
if (current == NULL) {
|
||||
*list = new_path;
|
||||
new_path->name_prev = NULL;
|
||||
} else {
|
||||
while (current->name_next) {
|
||||
current = current->name_next;
|
||||
}
|
||||
current->name_next = new_path;
|
||||
new_path->name_prev = current;
|
||||
}
|
||||
return new_path;
|
||||
}
|
||||
|
||||
/* Delete a given parameter from list and return pointer to next element*/
|
||||
struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev) {
|
||||
if (item == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct parameter_list *next;
|
||||
|
||||
if (item->name_next)
|
||||
next = item->name_next;
|
||||
else
|
||||
next = NULL;
|
||||
|
||||
if (next)
|
||||
next->name_prev = prev;
|
||||
|
||||
if (prev)
|
||||
prev->name_next = next;
|
||||
|
||||
if (item->name) {
|
||||
free(item->name);
|
||||
}
|
||||
free(item);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/* returns a pointer to the struct found in the list */
|
||||
struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
|
||||
struct parameter_list *temp_list;
|
||||
for (temp_list = list; temp_list; temp_list = temp_list->name_next) {
|
||||
if (!strcmp(temp_list->name, name))
|
||||
return temp_list;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
|
||||
struct parameter_list *d;
|
||||
for (d = desired; d; d = d->name_next) {
|
||||
if (!d->best_match) {
|
||||
struct mount_entry *me;
|
||||
size_t name_len = strlen(d->name);
|
||||
size_t best_match_len = 0;
|
||||
struct mount_entry *best_match = NULL;
|
||||
struct fs_usage fsp;
|
||||
|
||||
/* set best match if path name exactly matches a mounted device name */
|
||||
for (me = mount_list; me; me = me->me_next) {
|
||||
if (strcmp(me->me_devname, d->name) == 0) {
|
||||
if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
|
||||
best_match = me;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set best match by directory name if no match was found by devname */
|
||||
if (!best_match) {
|
||||
for (me = mount_list; me; me = me->me_next) {
|
||||
size_t len = strlen(me->me_mountdir);
|
||||
if ((!exact &&
|
||||
(best_match_len <= len && len <= name_len && (len == 1 || strncmp(me->me_mountdir, d->name, len) == 0))) ||
|
||||
(exact && strcmp(me->me_mountdir, d->name) == 0)) {
|
||||
if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
|
||||
best_match = me;
|
||||
best_match_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_match) {
|
||||
d->best_match = best_match;
|
||||
} else {
|
||||
d->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if name is in list */
|
||||
bool np_find_name(struct name_list *list, const char *name) {
|
||||
const struct name_list *n;
|
||||
|
||||
if (list == NULL || name == NULL) {
|
||||
return false;
|
||||
}
|
||||
for (n = list; n; n = n->next) {
|
||||
if (!strcmp(name, n->name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns true if name is in list */
|
||||
bool np_find_regmatch(struct regex_list *list, const char *name) {
|
||||
int len;
|
||||
regmatch_t m;
|
||||
|
||||
if (name == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
len = strlen(name);
|
||||
|
||||
for (; list; list = list->next) {
|
||||
/* Emulate a full match as if surrounded with ^( )$
|
||||
by checking whether the match spans the whole name */
|
||||
if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool np_seen_name(struct name_list *list, const char *name) {
|
||||
const struct name_list *s;
|
||||
for (s = list; s; s = s->next) {
|
||||
if (!strcmp(s->name, name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
|
||||
if (regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0 || regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* Header file for utils_disk */
|
||||
|
||||
#include "mountlist.h"
|
||||
#include "utils_base.h"
|
||||
#include "regex.h"
|
||||
|
||||
struct name_list {
|
||||
char *name;
|
||||
struct name_list *next;
|
||||
};
|
||||
|
||||
struct regex_list {
|
||||
regex_t regex;
|
||||
struct regex_list *next;
|
||||
};
|
||||
|
||||
struct parameter_list {
|
||||
char *name;
|
||||
thresholds *freespace_bytes;
|
||||
thresholds *freespace_units;
|
||||
thresholds *freespace_percent;
|
||||
thresholds *usedspace_bytes;
|
||||
thresholds *usedspace_units;
|
||||
thresholds *usedspace_percent;
|
||||
thresholds *usedinodes_percent;
|
||||
thresholds *freeinodes_percent;
|
||||
char *group;
|
||||
struct mount_entry *best_match;
|
||||
struct parameter_list *name_next;
|
||||
struct parameter_list *name_prev;
|
||||
uintmax_t total, available, available_to_root, used, inodes_free, inodes_free_to_root, inodes_used, inodes_total;
|
||||
double dfree_pct, dused_pct;
|
||||
uint64_t dused_units, dfree_units, dtotal_units;
|
||||
double dused_inodes_percent, dfree_inodes_percent;
|
||||
};
|
||||
|
||||
void np_add_name(struct name_list **list, const char *name);
|
||||
bool np_find_name(struct name_list *list, const char *name);
|
||||
bool np_seen_name(struct name_list *list, const char *name);
|
||||
int np_add_regex(struct regex_list **list, const char *regex, int cflags);
|
||||
bool np_find_regmatch(struct regex_list *list, const char *name);
|
||||
struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
|
||||
struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
|
||||
struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
|
||||
|
||||
int search_parameter_list(struct parameter_list *list, const char *name);
|
||||
void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact);
|
||||
bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re);
|
||||
|
|
@ -24,7 +24,9 @@ noinst_PROGRAMS = check_dhcp check_icmp @EXTRAS_ROOT@
|
|||
|
||||
EXTRA_PROGRAMS = pst3
|
||||
|
||||
EXTRA_DIST = t pst3.c
|
||||
EXTRA_DIST = t pst3.c \
|
||||
check_icmp.d \
|
||||
check_dhcp.d
|
||||
|
||||
BASEOBJS = ../plugins/utils.o ../lib/libmonitoringplug.a ../gl/libgnu.a
|
||||
NETOBJS = ../plugins/netutils.o $(BASEOBJS) $(EXTRA_NETOBJS)
|
||||
|
|
@ -82,6 +84,7 @@ install-exec-local: $(noinst_PROGRAMS)
|
|||
# the actual targets
|
||||
check_dhcp_LDADD = @LTLIBINTL@ $(NETLIBS) $(LIB_CRYPTO)
|
||||
check_icmp_LDADD = @LTLIBINTL@ $(NETLIBS) $(SOCKETLIBS) $(LIB_CRYPTO)
|
||||
check_icmp_SOURCES = check_icmp.c check_icmp.d/check_icmp_helpers.c
|
||||
|
||||
# -m64 needed at compiler and linker phase
|
||||
pst3_CFLAGS = @PST3CFLAGS@
|
||||
|
|
@ -89,7 +92,7 @@ pst3_LDFLAGS = @PST3CFLAGS@
|
|||
# pst3 must not use monitoringplug/gnulib includes!
|
||||
pst3_CPPFLAGS =
|
||||
|
||||
check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS)
|
||||
check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS)
|
||||
check_icmp_DEPENDENCIES = check_icmp.c $(NETOBJS)
|
||||
|
||||
clean-local:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
50
plugins-root/check_dhcp.d/config.h
Normal file
50
plugins-root/check_dhcp.d/config.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../config.h"
|
||||
#include "../lib/states.h"
|
||||
#include <stdbool.h>
|
||||
#include <netinet/in.h>
|
||||
#include "net/if.h"
|
||||
#include "output.h"
|
||||
|
||||
typedef struct requested_server_struct {
|
||||
struct in_addr server_address;
|
||||
bool answered;
|
||||
struct requested_server_struct *next;
|
||||
} requested_server;
|
||||
|
||||
typedef struct check_dhcp_config {
|
||||
bool unicast_mode; /* unicast mode: mimic a DHCP relay */
|
||||
bool exclusive_mode; /* exclusive mode aka "rogue DHCP server detection" */
|
||||
int num_of_requested_servers;
|
||||
struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
|
||||
struct in_addr requested_address;
|
||||
bool request_specific_address;
|
||||
|
||||
int dhcpoffer_timeout;
|
||||
unsigned char *user_specified_mac;
|
||||
char network_interface_name[IFNAMSIZ];
|
||||
requested_server *requested_server_list;
|
||||
|
||||
mp_output_format output_format;
|
||||
bool output_format_is_set;
|
||||
} check_dhcp_config;
|
||||
|
||||
check_dhcp_config check_dhcp_config_init(void) {
|
||||
check_dhcp_config tmp = {
|
||||
.unicast_mode = false,
|
||||
.exclusive_mode = false,
|
||||
.num_of_requested_servers = 0,
|
||||
.dhcp_ip = {0},
|
||||
.requested_address = {0},
|
||||
.request_specific_address = false,
|
||||
|
||||
.dhcpoffer_timeout = 2,
|
||||
.user_specified_mac = NULL,
|
||||
.network_interface_name = "eth0",
|
||||
.requested_server_list = NULL,
|
||||
|
||||
.output_format_is_set = false,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
134
plugins-root/check_icmp.d/check_icmp_helpers.c
Normal file
134
plugins-root/check_icmp.d/check_icmp_helpers.c
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "./config.h"
|
||||
#include <math.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include "./check_icmp_helpers.h"
|
||||
#include "../../plugins/netutils.h"
|
||||
|
||||
// timeout as a global variable to make it available to the timeout handler
|
||||
unsigned int timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
check_icmp_config check_icmp_config_init() {
|
||||
check_icmp_config tmp = {
|
||||
.modes =
|
||||
{
|
||||
.order_mode = false,
|
||||
.mos_mode = false,
|
||||
.rta_mode = false,
|
||||
.pl_mode = false,
|
||||
.jitter_mode = false,
|
||||
.score_mode = false,
|
||||
},
|
||||
|
||||
.min_hosts_alive = -1,
|
||||
.crit = {.pl = DEFAULT_CRIT_PL,
|
||||
.rta = DEFAULT_CRIT_RTA,
|
||||
.jitter = 50.0,
|
||||
.mos = 3.0,
|
||||
.score = 70.0},
|
||||
.warn = {.pl = DEFAULT_WARN_PL,
|
||||
.rta = DEFAULT_WARN_RTA,
|
||||
.jitter = 40.0,
|
||||
.mos = 3.5,
|
||||
.score = 80.0},
|
||||
|
||||
.ttl = DEFAULT_TTL,
|
||||
.icmp_data_size = DEFAULT_PING_DATA_SIZE,
|
||||
.target_interval = 0,
|
||||
.number_of_packets = DEFAULT_NUMBER_OF_PACKETS,
|
||||
|
||||
.source_ip = NULL,
|
||||
.need_v4 = false,
|
||||
.need_v6 = false,
|
||||
|
||||
.sender_id = 0,
|
||||
|
||||
.mode = MODE_RTA,
|
||||
|
||||
.number_of_targets = 0,
|
||||
.targets = NULL,
|
||||
|
||||
.number_of_hosts = 0,
|
||||
.hosts = NULL,
|
||||
|
||||
.output_format_is_set = false,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ping_target ping_target_init() {
|
||||
ping_target tmp = {
|
||||
.rtmin = INFINITY,
|
||||
|
||||
.jitter_min = INFINITY,
|
||||
|
||||
.found_out_of_order_packets = false,
|
||||
};
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
check_icmp_state check_icmp_state_init() {
|
||||
check_icmp_state tmp = {.icmp_sent = 0, .icmp_lost = 0, .icmp_recv = 0, .targets_down = 0};
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ping_target_create_wrapper ping_target_create(struct sockaddr_storage address) {
|
||||
ping_target_create_wrapper result = {
|
||||
.errorcode = OK,
|
||||
};
|
||||
|
||||
struct sockaddr_storage *tmp_addr = &address;
|
||||
|
||||
/* disregard obviously stupid addresses
|
||||
* (I didn't find an ipv6 equivalent to INADDR_NONE) */
|
||||
if (((tmp_addr->ss_family == AF_INET &&
|
||||
(((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_NONE ||
|
||||
((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_ANY))) ||
|
||||
(tmp_addr->ss_family == AF_INET6 &&
|
||||
(((struct sockaddr_in6 *)tmp_addr)->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
|
||||
result.errorcode = ERROR;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* add the fresh ip */
|
||||
ping_target target = ping_target_init();
|
||||
|
||||
/* fill out the sockaddr_storage struct */
|
||||
target.address = address;
|
||||
|
||||
result.host = target;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
check_icmp_target_container check_icmp_target_container_init() {
|
||||
check_icmp_target_container tmp = {
|
||||
.name = NULL,
|
||||
.number_of_targets = 0,
|
||||
.target_list = NULL,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned int ping_target_list_append(ping_target *list, ping_target *elem) {
|
||||
if (elem == NULL || list == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (list->next != NULL) {
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
list->next = elem;
|
||||
|
||||
unsigned int result = 1;
|
||||
|
||||
while (elem->next != NULL) {
|
||||
result++;
|
||||
elem = elem->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
68
plugins-root/check_icmp.d/check_icmp_helpers.h
Normal file
68
plugins-root/check_icmp.d/check_icmp_helpers.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../lib/states.h"
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
typedef struct ping_target {
|
||||
unsigned short id; /* id in **table, and icmp pkts */
|
||||
char *msg; /* icmp error message, if any */
|
||||
|
||||
struct sockaddr_storage address; /* the address of this host */
|
||||
struct sockaddr_storage error_addr; /* stores address of error replies */
|
||||
time_t time_waited; /* total time waited, in usecs */
|
||||
unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
|
||||
unsigned char icmp_type, icmp_code; /* type and code from errors */
|
||||
unsigned short flags; /* control/status flags */
|
||||
|
||||
double rtmax; /* max rtt */
|
||||
double rtmin; /* min rtt */
|
||||
|
||||
double jitter; /* measured jitter */
|
||||
double jitter_max; /* jitter rtt maximum */
|
||||
double jitter_min; /* jitter rtt minimum */
|
||||
|
||||
time_t last_tdiff;
|
||||
unsigned int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
|
||||
|
||||
bool found_out_of_order_packets;
|
||||
|
||||
struct ping_target *next;
|
||||
} ping_target;
|
||||
|
||||
ping_target ping_target_init();
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ping_target *target_list;
|
||||
unsigned int number_of_targets;
|
||||
} check_icmp_target_container;
|
||||
|
||||
check_icmp_target_container check_icmp_target_container_init();
|
||||
|
||||
typedef struct {
|
||||
unsigned int icmp_sent;
|
||||
unsigned int icmp_recv;
|
||||
unsigned int icmp_lost;
|
||||
unsigned short targets_down;
|
||||
} check_icmp_state;
|
||||
|
||||
check_icmp_state check_icmp_state_init();
|
||||
|
||||
typedef struct {
|
||||
int errorcode;
|
||||
ping_target host;
|
||||
} ping_target_create_wrapper;
|
||||
|
||||
typedef struct {
|
||||
int socket4;
|
||||
int socket6;
|
||||
} check_icmp_socket_set;
|
||||
|
||||
ping_target_create_wrapper ping_target_create(struct sockaddr_storage address);
|
||||
unsigned int ping_target_list_append(ping_target *list, ping_target *elem);
|
||||
115
plugins-root/check_icmp.d/config.h
Normal file
115
plugins-root/check_icmp.d/config.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../config.h"
|
||||
#include "../../lib/states.h"
|
||||
#include <stddef.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdint.h>
|
||||
#include "./check_icmp_helpers.h"
|
||||
#include "output.h"
|
||||
|
||||
/* threshold structure. all values are maximum allowed, exclusive */
|
||||
typedef struct {
|
||||
unsigned char pl; /* max allowed packet loss in percent */
|
||||
time_t rta; /* roundtrip time average, microseconds */
|
||||
double jitter; /* jitter time average, microseconds */
|
||||
double mos; /* MOS */
|
||||
double score; /* Score */
|
||||
} check_icmp_threshold;
|
||||
|
||||
/* the different modes of this program are as follows:
|
||||
* MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping)
|
||||
* MODE_HOSTCHECK: Return immediately upon any sign of life
|
||||
* In addition, sends packets to ALL addresses assigned
|
||||
* to this host (as returned by gethostbyname() or
|
||||
* gethostbyaddr() and expects one host only to be checked at
|
||||
* a time. Therefore, any packet response what so ever will
|
||||
* count as a sign of life, even when received outside
|
||||
* crit.rta limit. Do not misspell any additional IP's.
|
||||
* MODE_ALL: Requires packets from ALL requested IP to return OK (default).
|
||||
* MODE_ICMP: Default Mode
|
||||
*/
|
||||
typedef enum {
|
||||
MODE_RTA,
|
||||
MODE_HOSTCHECK,
|
||||
MODE_ALL,
|
||||
MODE_ICMP,
|
||||
} check_icmp_execution_mode;
|
||||
|
||||
typedef struct {
|
||||
bool order_mode;
|
||||
bool mos_mode;
|
||||
bool rta_mode;
|
||||
bool pl_mode;
|
||||
bool jitter_mode;
|
||||
bool score_mode;
|
||||
} check_icmp_mode_switches;
|
||||
|
||||
typedef struct {
|
||||
check_icmp_mode_switches modes;
|
||||
|
||||
int min_hosts_alive;
|
||||
check_icmp_threshold crit;
|
||||
check_icmp_threshold warn;
|
||||
|
||||
unsigned long ttl;
|
||||
unsigned short icmp_data_size;
|
||||
time_t target_interval;
|
||||
unsigned short number_of_packets;
|
||||
|
||||
char *source_ip;
|
||||
bool need_v4;
|
||||
bool need_v6;
|
||||
|
||||
uint16_t sender_id; // PID of the main process, which is used as an ID in packets
|
||||
|
||||
check_icmp_execution_mode mode;
|
||||
|
||||
unsigned short number_of_targets;
|
||||
ping_target *targets;
|
||||
|
||||
unsigned short number_of_hosts;
|
||||
check_icmp_target_container *hosts;
|
||||
|
||||
mp_output_format output_format;
|
||||
bool output_format_is_set;
|
||||
} check_icmp_config;
|
||||
|
||||
check_icmp_config check_icmp_config_init();
|
||||
|
||||
/* the data structure */
|
||||
typedef struct icmp_ping_data {
|
||||
struct timeval stime; /* timestamp (saved in protocol struct as well) */
|
||||
unsigned short ping_id;
|
||||
} icmp_ping_data;
|
||||
|
||||
#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */
|
||||
#define IP_HDR_SIZE 20
|
||||
#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN)
|
||||
#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data)
|
||||
#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44)
|
||||
|
||||
/* 80 msec packet interval by default */
|
||||
// DEPRECATED, remove when removing the option
|
||||
#define DEFAULT_PKT_INTERVAL 80000
|
||||
|
||||
#define DEFAULT_TARGET_INTERVAL 0
|
||||
|
||||
#define DEFAULT_WARN_RTA 200000
|
||||
#define DEFAULT_CRIT_RTA 500000
|
||||
#define DEFAULT_WARN_PL 40
|
||||
#define DEFAULT_CRIT_PL 80
|
||||
|
||||
#define DEFAULT_TIMEOUT 10
|
||||
#define DEFAULT_TTL 64
|
||||
|
||||
#define DEFAULT_NUMBER_OF_PACKETS 5
|
||||
|
||||
#define PACKET_BACKOFF_FACTOR 1.5
|
||||
#define TARGET_BACKOFF_FACTOR 1.5
|
||||
|
|
@ -12,14 +12,14 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
|
|||
"no" );
|
||||
|
||||
if ($allow_sudo eq "yes" or $> == 0) {
|
||||
plan tests => 6;
|
||||
plan tests => 7;
|
||||
} else {
|
||||
plan skip_all => "Need sudo to test check_dhcp";
|
||||
}
|
||||
my $sudo = $> == 0 ? '' : 'sudo';
|
||||
|
||||
my $successOutput = '/OK: Received \d+ DHCPOFFER\(s\), \d+ of 1 requested servers responded, max lease time = \d+ sec\./';
|
||||
my $failureOutput = '/CRITICAL: (No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/';
|
||||
my $successOutput = '/Received \d+ DHCPOFFER(s)*, max lease time = \d+ seconds/';
|
||||
my $failureOutput = '/(No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/';
|
||||
my $invalidOutput = '/Invalid hostname/';
|
||||
|
||||
my $host_responsive = getTestParameter( "NP_HOST_DHCP_RESPONSIVE",
|
||||
|
|
@ -34,6 +34,8 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
|
|||
"An invalid (not known to DNS) hostname",
|
||||
"nosuchhost" );
|
||||
|
||||
my $output_format = "--output-format mp-test-json";
|
||||
|
||||
# try to determince interface
|
||||
my $interface = '';
|
||||
|
||||
|
|
@ -49,19 +51,21 @@ my $res;
|
|||
SKIP: {
|
||||
skip('need responsive test host', 2) unless $host_responsive;
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_dhcp $interface -u -s $host_responsive"
|
||||
"$sudo ./check_dhcp $interface -u -s $host_responsive $output_format"
|
||||
);
|
||||
is( $res->return_code, 0, "Syntax ok" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
is( $res->return_code, 0, "with JSON test format result should always be OK" );
|
||||
like( $res->{'mp_test_result'}->{'state'}, "/OK/", "Output OK" );
|
||||
like( $res->{'mp_test_result'}->{'checks'}->[0]->{'output'}, $successOutput, "Output OK" );
|
||||
};
|
||||
|
||||
SKIP: {
|
||||
skip('need nonresponsive test host', 2) unless $host_nonresponsive;
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_dhcp $interface -u -s $host_nonresponsive"
|
||||
"$sudo ./check_dhcp $interface -u -s $host_nonresponsive $output_format"
|
||||
);
|
||||
is( $res->return_code, 2, "Exit code - host nonresponsive" );
|
||||
like( $res->output, $failureOutput, "Output OK" );
|
||||
is( $res->return_code, 0, "with JSON test format result should always be OK" );
|
||||
like( $res->{'mp_test_result'}->{'state'}, "/CRITICAL/", "Exit code - host nonresponsive" );
|
||||
like( $res->{'mp_test_result'}->{'checks'}->[0]->{'output'}, $failureOutput, "Output OK" );
|
||||
};
|
||||
|
||||
SKIP: {
|
||||
|
|
@ -69,6 +73,6 @@ SKIP: {
|
|||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_dhcp $interface -u -s $hostname_invalid"
|
||||
);
|
||||
is( $res->return_code, 3, "Exit code - host invalid" );
|
||||
is( $res->return_code, 3, "invalid hostname/address should return UNKNOWN" );
|
||||
like( $res->output, $invalidOutput, "Output OK" );
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,15 +12,12 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
|
|||
"no" );
|
||||
|
||||
if ($allow_sudo eq "yes" or $> == 0) {
|
||||
plan tests => 40;
|
||||
plan tests => 17;
|
||||
} else {
|
||||
plan skip_all => "Need sudo to test check_icmp";
|
||||
}
|
||||
my $sudo = $> == 0 ? '' : 'sudo';
|
||||
|
||||
my $successOutput = '/OK - .*? rta (?:[\d\.]+ms)|(?:nan), lost \d+%/';
|
||||
my $failureOutput = '/(WARNING|CRITICAL) - .*? rta (?:[\d\.]+ms > [\d\.]+ms|nan)/';
|
||||
|
||||
my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE",
|
||||
"The hostname of system responsive to network requests",
|
||||
"localhost" );
|
||||
|
|
@ -36,108 +33,85 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
|
|||
my $res;
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -w 10000ms,100% -c 10000ms,100%"
|
||||
"$sudo ./check_icmp -H $host_responsive -w 100ms,100% -c 100ms,100%"
|
||||
);
|
||||
is( $res->return_code, 0, "Syntax ok" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -w 0ms,0% -c 10000ms,100%"
|
||||
"$sudo ./check_icmp -H $host_responsive -w 0ms,0% -c 100ms,100%"
|
||||
);
|
||||
is( $res->return_code, 1, "Syntax ok, with forced warning" );
|
||||
like( $res->output, $failureOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -w 0,0% -c 0,0%"
|
||||
);
|
||||
is( $res->return_code, 2, "Syntax ok, with forced critical" );
|
||||
like( $res->output, $failureOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2"
|
||||
"$sudo ./check_icmp -H $host_nonresponsive -w 100ms,100% -c 100ms,100%"
|
||||
);
|
||||
is( $res->return_code, 2, "Timeout - host nonresponsive" );
|
||||
like( $res->output, '/pl=100%/', "Error contains 'pl=100%' string (for 100% packet loss)" );
|
||||
like( $res->output, '/rta=U/', "Error contains 'rta=U' string" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -w 10000ms,100% -c 10000ms,100%"
|
||||
"$sudo ./check_icmp -w 100ms,100% -c 100ms,100%"
|
||||
);
|
||||
is( $res->return_code, 3, "No hostname" );
|
||||
like( $res->output, '/No hosts to check/', "Output with appropriate error message");
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2"
|
||||
"$sudo ./check_icmp -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 0"
|
||||
);
|
||||
is( $res->return_code, 0, "One host nonresponsive - zero required" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 1"
|
||||
);
|
||||
is( $res->return_code, 0, "One of two host nonresponsive - one required" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 2"
|
||||
);
|
||||
is( $res->return_code, 2, "One of two host nonresponsive - two required" );
|
||||
like( $res->output, $failureOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 10000ms,100% -c 10000ms,100% -n 1 -m 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 100ms,100% -c 100ms,100% -n 1"
|
||||
);
|
||||
is( $res->return_code, 0, "IPv4 source_ip accepted" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -b 65507"
|
||||
);
|
||||
is( $res->return_code, 0, "Try max packet size" );
|
||||
like( $res->output, $successOutput, "Output OK - Didn't overflow" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1"
|
||||
);
|
||||
is( $res->return_code, 0, "rta works" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1"
|
||||
);
|
||||
is( $res->return_code, 0, "pl works" );
|
||||
like( $res->output, '/lost 0%/', "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -J 80,90"
|
||||
);
|
||||
is( $res->return_code, 0, "jitter works" );
|
||||
like( $res->output, '/jitter \d/', "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -M 4,3"
|
||||
);
|
||||
is( $res->return_code, 0, "mos works" );
|
||||
like( $res->output, '/MOS \d/', "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -S 80,70"
|
||||
);
|
||||
is( $res->return_code, 0, "score works" );
|
||||
like( $res->output, '/Score \d/', "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -O -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -O"
|
||||
);
|
||||
is( $res->return_code, 0, "order works" );
|
||||
like( $res->output, '/Packets in order/', "Output OK" );
|
||||
|
||||
$res = NPTest->testCmd(
|
||||
"$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2"
|
||||
"$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100"
|
||||
);
|
||||
is( $res->return_code, 0, "order works" );
|
||||
like( $res->output, '/Packets in order/', "Output OK" );
|
||||
like( $res->output, '/Score \d/', "Output OK" );
|
||||
like( $res->output, '/MOS \d/', "Output OK" );
|
||||
like( $res->output, '/jitter \d/', "Output OK" );
|
||||
like( $res->output, '/lost 0%/', "Output OK" );
|
||||
like( $res->output, $successOutput, "Output OK" );
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ MATHLIBS = @MATHLIBS@
|
|||
#AM_CFLAGS = -Wall
|
||||
|
||||
libexec_PROGRAMS = check_apt check_cluster check_disk check_dummy check_http check_load \
|
||||
check_mrtg check_mrtgtraf check_ntp check_ntp_peer check_nwstat check_ping \
|
||||
check_mrtg check_mrtgtraf check_ntp check_ntp_peer check_ping \
|
||||
check_real check_smtp check_ssh check_tcp check_time check_ntp_time \
|
||||
check_ups check_users negate \
|
||||
urlize @EXTRAS@
|
||||
|
|
@ -40,11 +40,13 @@ EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \
|
|||
check_nagios check_by_ssh check_dns check_nt check_ide_smart \
|
||||
check_procs check_mysql_query check_apt check_dbi check_curl \
|
||||
\
|
||||
tests/test_check_swap
|
||||
tests/test_check_swap \
|
||||
tests/test_check_disk
|
||||
|
||||
SUBDIRS = picohttpparser
|
||||
|
||||
np_test_scripts = tests/test_check_swap.t
|
||||
np_test_scripts = tests/test_check_swap.t \
|
||||
tests/test_check_disk.t
|
||||
|
||||
EXTRA_DIST = t \
|
||||
tests \
|
||||
|
|
@ -55,6 +57,7 @@ EXTRA_DIST = t \
|
|||
check_hpjd.d \
|
||||
check_game.d \
|
||||
check_radius.d \
|
||||
check_disk.d \
|
||||
check_time.d \
|
||||
check_load.d \
|
||||
check_nagios.d \
|
||||
|
|
@ -70,6 +73,7 @@ EXTRA_DIST = t \
|
|||
check_ntp_peer.d \
|
||||
check_apt.d \
|
||||
check_pgsql.d \
|
||||
check_procs.d \
|
||||
check_ping.d \
|
||||
check_by_ssh.d \
|
||||
check_smtp.d \
|
||||
|
|
@ -120,6 +124,7 @@ check_curl_LDADD = $(NETLIBS) $(LIBCURLLIBS) $(SSLOBJS) $(URIPARSERLIBS) picohtt
|
|||
check_dbi_LDADD = $(NETLIBS) $(DBILIBS)
|
||||
check_dig_LDADD = $(NETLIBS)
|
||||
check_disk_LDADD = $(BASEOBJS)
|
||||
check_disk_SOURCES = check_disk.c check_disk.d/utils_disk.c
|
||||
check_dns_LDADD = $(NETLIBS)
|
||||
check_dummy_LDADD = $(BASEOBJS)
|
||||
check_fping_LDADD = $(NETLIBS)
|
||||
|
|
@ -140,7 +145,6 @@ check_nagios_LDADD = $(BASEOBJS)
|
|||
check_nt_LDADD = $(NETLIBS)
|
||||
check_ntp_LDADD = $(NETLIBS) $(MATHLIBS)
|
||||
check_ntp_peer_LDADD = $(NETLIBS) $(MATHLIBS)
|
||||
check_nwstat_LDADD = $(NETLIBS)
|
||||
check_pgsql_LDADD = $(NETLIBS) $(PGLIBS)
|
||||
check_ping_LDADD = $(NETLIBS)
|
||||
check_procs_LDADD = $(BASEOBJS)
|
||||
|
|
@ -167,6 +171,8 @@ endif
|
|||
|
||||
tests_test_check_swap_LDADD = $(BASEOBJS) $(tap_ldflags) -ltap
|
||||
tests_test_check_swap_SOURCES = tests/test_check_swap.c check_swap.d/swap.c
|
||||
tests_test_check_disk_LDADD = $(BASEOBJS) $(tap_ldflags) check_disk.d/utils_disk.c -ltap
|
||||
tests_test_check_disk_SOURCES = tests/test_check_disk.c
|
||||
|
||||
##############################################################################
|
||||
# secondary dependencies
|
||||
|
|
|
|||
1373
plugins/check_disk.c
1373
plugins/check_disk.c
File diff suppressed because it is too large
Load diff
517
plugins/check_disk.d/utils_disk.c
Normal file
517
plugins/check_disk.d/utils_disk.c
Normal file
|
|
@ -0,0 +1,517 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* Library for check_disk
|
||||
*
|
||||
* License: GPL
|
||||
* Copyright (c) 1999-2024 Monitoring Plugins Development Team
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This file contains utilities for check_disk. These are tested by libtap
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
#include "utils_disk.h"
|
||||
#include "../../gl/fsusage.h"
|
||||
#include "../../lib/thresholds.h"
|
||||
#include "../../lib/states.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
void np_add_name(struct name_list **list, const char *name) {
|
||||
struct name_list *new_entry;
|
||||
new_entry = (struct name_list *)malloc(sizeof *new_entry);
|
||||
new_entry->name = (char *)name;
|
||||
new_entry->next = *list;
|
||||
*list = new_entry;
|
||||
}
|
||||
|
||||
/* @brief Initialises a new regex at the begin of list via regcomp(3)
|
||||
*
|
||||
* @details if the regex fails to compile the error code of regcomp(3) is returned
|
||||
* and list is not modified, otherwise list is modified to point to the new
|
||||
* element
|
||||
* @param list Pointer to a linked list of regex_list elements
|
||||
* @param regex the string containing the regex which should be inserted into the list
|
||||
* @param clags the cflags parameter for regcomp(3)
|
||||
*/
|
||||
int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
|
||||
struct regex_list *new_entry = (struct regex_list *)malloc(sizeof *new_entry);
|
||||
|
||||
if (new_entry == NULL) {
|
||||
die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
|
||||
}
|
||||
|
||||
int regcomp_result = regcomp(&new_entry->regex, regex, cflags);
|
||||
|
||||
if (!regcomp_result) {
|
||||
// regcomp succeeded
|
||||
new_entry->next = *list;
|
||||
*list = new_entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
// regcomp failed
|
||||
free(new_entry);
|
||||
|
||||
return regcomp_result;
|
||||
}
|
||||
|
||||
parameter_list_elem parameter_list_init(const char *name) {
|
||||
parameter_list_elem result = {
|
||||
.name = strdup(name),
|
||||
.best_match = NULL,
|
||||
|
||||
.freespace_units = mp_thresholds_init(),
|
||||
.freespace_percent = mp_thresholds_init(),
|
||||
.freeinodes_percent = mp_thresholds_init(),
|
||||
|
||||
.group = NULL,
|
||||
|
||||
.inodes_total = 0,
|
||||
.inodes_free = 0,
|
||||
.inodes_free_to_root = 0,
|
||||
.inodes_used = 0,
|
||||
|
||||
.used_bytes = 0,
|
||||
.free_bytes = 0,
|
||||
.total_bytes = 0,
|
||||
|
||||
.next = NULL,
|
||||
.prev = NULL,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Returns true if name is in list */
|
||||
bool np_find_name(struct name_list *list, const char *name) {
|
||||
if (list == NULL || name == NULL) {
|
||||
return false;
|
||||
}
|
||||
for (struct name_list *iterator = list; iterator; iterator = iterator->next) {
|
||||
if (!strcmp(name, iterator->name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns true if name is in list */
|
||||
bool np_find_regmatch(struct regex_list *list, const char *name) {
|
||||
if (name == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = strlen(name);
|
||||
|
||||
for (; list; list = list->next) {
|
||||
/* Emulate a full match as if surrounded with ^( )$
|
||||
by checking whether the match spans the whole name */
|
||||
regmatch_t dummy_match;
|
||||
if (!regexec(&list->regex, name, 1, &dummy_match, 0) && dummy_match.rm_so == 0 && dummy_match.rm_eo == len) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool np_seen_name(struct name_list *list, const char *name) {
|
||||
for (struct name_list *iterator = list; iterator; iterator = iterator->next) {
|
||||
if (!strcmp(iterator->name, name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
|
||||
return ((regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0) || (regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0));
|
||||
}
|
||||
|
||||
check_disk_config check_disk_config_init() {
|
||||
check_disk_config tmp = {
|
||||
.erronly = false,
|
||||
.display_mntp = false,
|
||||
.show_local_fs = false,
|
||||
.stat_remote_fs = false,
|
||||
.display_inodes_perfdata = false,
|
||||
|
||||
.exact_match = false,
|
||||
.freespace_ignore_reserved = false,
|
||||
|
||||
.ignore_missing = false,
|
||||
.path_ignored = false,
|
||||
|
||||
// FS Filters
|
||||
.fs_exclude_list = NULL,
|
||||
.fs_include_list = NULL,
|
||||
.device_path_exclude_list = NULL,
|
||||
|
||||
// Actual filesystems paths to investigate
|
||||
.path_select_list = filesystem_list_init(),
|
||||
|
||||
.mount_list = NULL,
|
||||
.seen = NULL,
|
||||
|
||||
.display_unit = Humanized,
|
||||
// .unit = MebiBytes,
|
||||
|
||||
.output_format_is_set = false,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char *get_unit_string(byte_unit_enum unit) {
|
||||
switch (unit) {
|
||||
case Bytes:
|
||||
return "Bytes";
|
||||
case KibiBytes:
|
||||
return "KiB";
|
||||
case MebiBytes:
|
||||
return "MiB";
|
||||
case GibiBytes:
|
||||
return "GiB";
|
||||
case TebiBytes:
|
||||
return "TiB";
|
||||
case PebiBytes:
|
||||
return "PiB";
|
||||
case ExbiBytes:
|
||||
return "EiB";
|
||||
case KiloBytes:
|
||||
return "KB";
|
||||
case MegaBytes:
|
||||
return "MB";
|
||||
case GigaBytes:
|
||||
return "GB";
|
||||
case TeraBytes:
|
||||
return "TB";
|
||||
case PetaBytes:
|
||||
return "PB";
|
||||
case ExaBytes:
|
||||
return "EB";
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
measurement_unit measurement_unit_init() {
|
||||
measurement_unit tmp = {
|
||||
.name = NULL,
|
||||
.filesystem_type = NULL,
|
||||
.is_group = false,
|
||||
|
||||
.freeinodes_percent_thresholds = mp_thresholds_init(),
|
||||
.freespace_percent_thresholds = mp_thresholds_init(),
|
||||
.freespace_bytes_thresholds = mp_thresholds_init(),
|
||||
|
||||
.free_bytes = 0,
|
||||
.used_bytes = 0,
|
||||
.total_bytes = 0,
|
||||
|
||||
.inodes_total = 0,
|
||||
.inodes_free = 0,
|
||||
.inodes_free_to_root = 0,
|
||||
.inodes_used = 0,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Add a given element to the list, memory for the new element is freshly allocated
|
||||
// Returns a pointer to new element
|
||||
measurement_unit_list *add_measurement_list(measurement_unit_list *list, measurement_unit elem) {
|
||||
// find last element
|
||||
measurement_unit_list *new = NULL;
|
||||
if (list == NULL) {
|
||||
new = calloc(1, sizeof(measurement_unit_list));
|
||||
if (new == NULL) {
|
||||
die(STATE_UNKNOWN, _("allocation failed"));
|
||||
}
|
||||
} else {
|
||||
measurement_unit_list *list_elem = list;
|
||||
while (list_elem->next != NULL) {
|
||||
list_elem = list_elem->next;
|
||||
}
|
||||
|
||||
new = calloc(1, sizeof(measurement_unit_list));
|
||||
if (new == NULL) {
|
||||
die(STATE_UNKNOWN, _("allocation failed"));
|
||||
}
|
||||
|
||||
list_elem->next = new;
|
||||
}
|
||||
|
||||
new->unit = elem;
|
||||
new->next = NULL;
|
||||
return new;
|
||||
}
|
||||
|
||||
measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, parameter_list_elem filesystem) {
|
||||
|
||||
unit.free_bytes += filesystem.free_bytes;
|
||||
unit.used_bytes += filesystem.used_bytes;
|
||||
unit.total_bytes += filesystem.total_bytes;
|
||||
|
||||
unit.inodes_total += filesystem.inodes_total;
|
||||
unit.inodes_free += filesystem.inodes_free;
|
||||
unit.inodes_free_to_root += filesystem.inodes_free_to_root;
|
||||
unit.inodes_used += filesystem.inodes_used;
|
||||
return unit;
|
||||
}
|
||||
|
||||
measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, bool display_mntp) {
|
||||
measurement_unit result = measurement_unit_init();
|
||||
if (!display_mntp) {
|
||||
result.name = strdup(filesystem.best_match->me_mountdir);
|
||||
} else {
|
||||
result.name = strdup(filesystem.best_match->me_devname);
|
||||
}
|
||||
|
||||
if (filesystem.group) {
|
||||
result.is_group = true;
|
||||
} else {
|
||||
result.is_group = false;
|
||||
if (filesystem.best_match) {
|
||||
result.filesystem_type = filesystem.best_match->me_type;
|
||||
}
|
||||
}
|
||||
|
||||
result.freeinodes_percent_thresholds = filesystem.freeinodes_percent;
|
||||
result.freespace_percent_thresholds = filesystem.freespace_percent;
|
||||
result.freespace_bytes_thresholds = filesystem.freespace_units;
|
||||
result.free_bytes = filesystem.free_bytes;
|
||||
result.total_bytes = filesystem.total_bytes;
|
||||
result.used_bytes = filesystem.used_bytes;
|
||||
result.inodes_total = filesystem.inodes_total;
|
||||
result.inodes_used = filesystem.inodes_used;
|
||||
result.inodes_free = filesystem.inodes_free;
|
||||
result.inodes_free_to_root = filesystem.inodes_free_to_root;
|
||||
return result;
|
||||
}
|
||||
|
||||
#define RANDOM_STRING_LENGTH 64
|
||||
|
||||
char *humanize_byte_value(unsigned long long value, bool use_si_units) {
|
||||
// Idea: A reasonable output should have at most 3 orders of magnitude
|
||||
// before the decimal separator
|
||||
// 353GiB is ok, 2444 GiB should be 2.386 TiB
|
||||
char *result = calloc(RANDOM_STRING_LENGTH, sizeof(char));
|
||||
if (result == NULL) {
|
||||
die(STATE_UNKNOWN, _("allocation failed"));
|
||||
}
|
||||
const byte_unit KibiBytes_factor = 1024;
|
||||
const byte_unit MebiBytes_factor = 1048576;
|
||||
const byte_unit GibiBytes_factor = 1073741824;
|
||||
const byte_unit TebiBytes_factor = 1099511627776;
|
||||
const byte_unit PebiBytes_factor = 1125899906842624;
|
||||
const byte_unit ExbiBytes_factor = 1152921504606846976;
|
||||
const byte_unit KiloBytes_factor = 1000;
|
||||
const byte_unit MegaBytes_factor = 1000000;
|
||||
const byte_unit GigaBytes_factor = 1000000000;
|
||||
const byte_unit TeraBytes_factor = 1000000000000;
|
||||
const byte_unit PetaBytes_factor = 1000000000000000;
|
||||
const byte_unit ExaBytes_factor = 1000000000000000000;
|
||||
|
||||
if (use_si_units) {
|
||||
// SI units, powers of 10
|
||||
if (value < KiloBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu B", value);
|
||||
} else if (value < MegaBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu KB", value / KiloBytes_factor);
|
||||
} else if (value < GigaBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu MB", value / MegaBytes_factor);
|
||||
} else if (value < TeraBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu GB", value / GigaBytes_factor);
|
||||
} else if (value < PetaBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu TB", value / TeraBytes_factor);
|
||||
} else if (value < ExaBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu PB", value / PetaBytes_factor);
|
||||
} else {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu EB", value / ExaBytes_factor);
|
||||
}
|
||||
} else {
|
||||
// IEC units, powers of 2 ^ 10
|
||||
if (value < KibiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu B", value);
|
||||
} else if (value < MebiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu KiB", value / KibiBytes_factor);
|
||||
} else if (value < GibiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu MiB", value / MebiBytes_factor);
|
||||
} else if (value < TebiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu GiB", value / GibiBytes_factor);
|
||||
} else if (value < PebiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu TiB", value / TebiBytes_factor);
|
||||
} else if (value < ExbiBytes_factor) {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu PiB", value / PebiBytes_factor);
|
||||
} else {
|
||||
snprintf(result, RANDOM_STRING_LENGTH, "%llu EiB", value / ExbiBytes_factor);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
filesystem_list filesystem_list_init() {
|
||||
filesystem_list tmp = {
|
||||
.length = 0,
|
||||
.first = NULL,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
parameter_list_elem *mp_int_fs_list_append(filesystem_list *list, const char *name) {
|
||||
parameter_list_elem *current = list->first;
|
||||
parameter_list_elem *new_path = (struct parameter_list *)malloc(sizeof *new_path);
|
||||
*new_path = parameter_list_init(name);
|
||||
|
||||
if (current == NULL) {
|
||||
list->first = new_path;
|
||||
new_path->prev = NULL;
|
||||
list->length = 1;
|
||||
} else {
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
current->next = new_path;
|
||||
new_path->prev = current;
|
||||
list->length++;
|
||||
}
|
||||
return new_path;
|
||||
}
|
||||
|
||||
parameter_list_elem *mp_int_fs_list_find(filesystem_list list, const char *name) {
|
||||
if (list.length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (parameter_list_elem *temp_list = list.first; temp_list; temp_list = temp_list->next) {
|
||||
if (!strcmp(temp_list->name, name)) {
|
||||
return temp_list;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parameter_list_elem *mp_int_fs_list_del(filesystem_list *list, parameter_list_elem *item) {
|
||||
if (list->length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
// Got NULL for item, interpret this as "delete first element"
|
||||
// as a kind of compatibility to the old function
|
||||
item = list->first;
|
||||
}
|
||||
|
||||
if (list->first == item) {
|
||||
list->length--;
|
||||
|
||||
list->first = item->next;
|
||||
if (list->first) {
|
||||
list->first->prev = NULL;
|
||||
}
|
||||
return list->first;
|
||||
}
|
||||
|
||||
// Was not the first element, continue
|
||||
parameter_list_elem *prev = list->first;
|
||||
parameter_list_elem *current = list->first->next;
|
||||
|
||||
while (current != item && current != NULL) {
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current == NULL) {
|
||||
// didn't find that element ....
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// remove the element
|
||||
parameter_list_elem *next = current->next;
|
||||
prev->next = next;
|
||||
list->length--;
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
if (item->name) {
|
||||
free(item->name);
|
||||
}
|
||||
free(item);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
parameter_list_elem *mp_int_fs_list_get_next(parameter_list_elem *current) {
|
||||
if (!current) {
|
||||
return NULL;
|
||||
}
|
||||
return current->next;
|
||||
}
|
||||
|
||||
void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, bool exact) {
|
||||
for (parameter_list_elem *elem = list.first; elem; elem = mp_int_fs_list_get_next(elem)) {
|
||||
if (!elem->best_match) {
|
||||
size_t name_len = strlen(elem->name);
|
||||
struct mount_entry *best_match = NULL;
|
||||
|
||||
/* set best match if path name exactly matches a mounted device name */
|
||||
for (struct mount_entry *mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) {
|
||||
if (strcmp(mount_entry->me_devname, elem->name) == 0) {
|
||||
struct fs_usage fsp;
|
||||
if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) {
|
||||
best_match = mount_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set best match by directory name if no match was found by devname */
|
||||
if (!best_match) {
|
||||
size_t best_match_len = 0;
|
||||
for (struct mount_entry *mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) {
|
||||
size_t len = strlen(mount_entry->me_mountdir);
|
||||
|
||||
if ((!exact && (best_match_len <= len && len <= name_len &&
|
||||
(len == 1 || strncmp(mount_entry->me_mountdir, elem->name, len) == 0))) ||
|
||||
(exact && strcmp(mount_entry->me_mountdir, elem->name) == 0)) {
|
||||
struct fs_usage fsp;
|
||||
|
||||
if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) {
|
||||
best_match = mount_entry;
|
||||
best_match_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_match) {
|
||||
elem->best_match = best_match;
|
||||
} else {
|
||||
elem->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */
|
||||
}
|
||||
|
||||
// No filesystem without a mount_entry!
|
||||
// assert(elem->best_match != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
157
plugins/check_disk.d/utils_disk.h
Normal file
157
plugins/check_disk.d/utils_disk.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#pragma once
|
||||
/* Header file for utils_disk */
|
||||
|
||||
#include "../../config.h"
|
||||
#include "../../gl/mountlist.h"
|
||||
#include "../../lib/utils_base.h"
|
||||
#include "../../lib/output.h"
|
||||
#include "regex.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long long byte_unit;
|
||||
|
||||
typedef enum {
|
||||
Humanized,
|
||||
Bytes,
|
||||
KibiBytes,
|
||||
MebiBytes,
|
||||
GibiBytes,
|
||||
TebiBytes,
|
||||
PebiBytes,
|
||||
ExbiBytes,
|
||||
KiloBytes,
|
||||
MegaBytes,
|
||||
GigaBytes,
|
||||
TeraBytes,
|
||||
PetaBytes,
|
||||
ExaBytes,
|
||||
} byte_unit_enum;
|
||||
|
||||
typedef struct name_list string_list;
|
||||
struct name_list {
|
||||
char *name;
|
||||
string_list *next;
|
||||
};
|
||||
|
||||
struct regex_list {
|
||||
regex_t regex;
|
||||
struct regex_list *next;
|
||||
};
|
||||
|
||||
typedef struct parameter_list parameter_list_elem;
|
||||
struct parameter_list {
|
||||
char *name;
|
||||
char *group;
|
||||
|
||||
mp_thresholds freespace_units;
|
||||
mp_thresholds freespace_percent;
|
||||
mp_thresholds freeinodes_percent;
|
||||
|
||||
struct mount_entry *best_match;
|
||||
|
||||
uintmax_t inodes_free_to_root;
|
||||
uintmax_t inodes_free;
|
||||
uintmax_t inodes_used;
|
||||
uintmax_t inodes_total;
|
||||
|
||||
uint64_t used_bytes;
|
||||
uint64_t free_bytes;
|
||||
uint64_t total_bytes;
|
||||
|
||||
parameter_list_elem *next;
|
||||
parameter_list_elem *prev;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
size_t length;
|
||||
parameter_list_elem *first;
|
||||
} filesystem_list;
|
||||
|
||||
filesystem_list filesystem_list_init();
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *filesystem_type;
|
||||
bool is_group;
|
||||
|
||||
mp_thresholds freespace_bytes_thresholds;
|
||||
mp_thresholds freespace_percent_thresholds;
|
||||
mp_thresholds freeinodes_percent_thresholds;
|
||||
|
||||
uintmax_t inodes_free_to_root;
|
||||
uintmax_t inodes_free;
|
||||
uintmax_t inodes_used;
|
||||
uintmax_t inodes_total;
|
||||
|
||||
uintmax_t used_bytes;
|
||||
uintmax_t free_bytes;
|
||||
uintmax_t total_bytes;
|
||||
} measurement_unit;
|
||||
|
||||
typedef struct measurement_unit_list measurement_unit_list;
|
||||
struct measurement_unit_list {
|
||||
measurement_unit unit;
|
||||
measurement_unit_list *next;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
// Output options
|
||||
bool erronly;
|
||||
bool display_mntp;
|
||||
/* show only local filesystems. */
|
||||
bool show_local_fs;
|
||||
/* show only local filesystems but call stat() on remote ones. */
|
||||
bool stat_remote_fs;
|
||||
bool display_inodes_perfdata;
|
||||
|
||||
bool exact_match;
|
||||
bool freespace_ignore_reserved;
|
||||
|
||||
bool ignore_missing;
|
||||
bool path_ignored;
|
||||
|
||||
/* Linked list of filesystem types to omit.
|
||||
If the list is empty, don't exclude any types. */
|
||||
struct regex_list *fs_exclude_list;
|
||||
/* Linked list of filesystem types to check.
|
||||
If the list is empty, include all types. */
|
||||
struct regex_list *fs_include_list;
|
||||
struct name_list *device_path_exclude_list;
|
||||
filesystem_list path_select_list;
|
||||
/* Linked list of mounted filesystems. */
|
||||
struct mount_entry *mount_list;
|
||||
struct name_list *seen;
|
||||
|
||||
byte_unit_enum display_unit;
|
||||
// byte_unit unit;
|
||||
|
||||
bool output_format_is_set;
|
||||
mp_output_format output_format;
|
||||
} check_disk_config;
|
||||
|
||||
void np_add_name(struct name_list **list, const char *name);
|
||||
bool np_find_name(struct name_list *list, const char *name);
|
||||
bool np_seen_name(struct name_list *list, const char *name);
|
||||
int np_add_regex(struct regex_list **list, const char *regex, int cflags);
|
||||
bool np_find_regmatch(struct regex_list *list, const char *name);
|
||||
|
||||
parameter_list_elem parameter_list_init(const char *);
|
||||
|
||||
parameter_list_elem *mp_int_fs_list_append(filesystem_list *list, const char *name);
|
||||
parameter_list_elem *mp_int_fs_list_find(filesystem_list list, const char *name);
|
||||
parameter_list_elem *mp_int_fs_list_del(filesystem_list *list, parameter_list_elem *item);
|
||||
parameter_list_elem *mp_int_fs_list_get_next(parameter_list_elem *current);
|
||||
void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, bool exact);
|
||||
|
||||
measurement_unit measurement_unit_init();
|
||||
measurement_unit_list *add_measurement_list(measurement_unit_list *list, measurement_unit elem);
|
||||
measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, parameter_list_elem filesystem);
|
||||
measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, bool display_mntp);
|
||||
|
||||
int search_parameter_list(parameter_list_elem *list, const char *name);
|
||||
bool np_regex_match_mount_entry(struct mount_entry *, regex_t *);
|
||||
|
||||
char *get_unit_string(byte_unit_enum);
|
||||
check_disk_config check_disk_config_init();
|
||||
|
||||
char *humanize_byte_value(unsigned long long value, bool use_si_units);
|
||||
|
|
@ -79,6 +79,24 @@ int main(int argc, char **argv) {
|
|||
server = strscpy(server, config.server_name);
|
||||
|
||||
char *option_string = "";
|
||||
char *fping_prog = NULL;
|
||||
|
||||
/* First determine if the target is dualstack or ipv6 only. */
|
||||
bool server_is_inet6_addr = is_inet6_addr(server);
|
||||
|
||||
/*
|
||||
* If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
|
||||
* -> we use ipv6
|
||||
* If the user requested -4 OR the user made no assertion and the address is v4 ONLY
|
||||
* -> we use ipv4
|
||||
*/
|
||||
if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
|
||||
xasprintf(&option_string, "%s-6 ", option_string);
|
||||
} else {
|
||||
xasprintf(&option_string, "%s-4 ", option_string);
|
||||
}
|
||||
fping_prog = strdup(PATH_TO_FPING);
|
||||
|
||||
/* compose the command */
|
||||
if (config.target_timeout) {
|
||||
xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
|
||||
|
|
@ -99,19 +117,26 @@ int main(int argc, char **argv) {
|
|||
xasprintf(&option_string, "%s-R ", option_string);
|
||||
}
|
||||
|
||||
char *fping_prog = NULL;
|
||||
#ifdef PATH_TO_FPING6
|
||||
if (address_family != AF_INET && is_inet6_addr(server)) {
|
||||
fping_prog = strdup(PATH_TO_FPING6);
|
||||
} else {
|
||||
fping_prog = strdup(PATH_TO_FPING);
|
||||
if (config.fwmark_set) {
|
||||
xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
|
||||
}
|
||||
|
||||
if (config.icmp_timestamp) {
|
||||
xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
|
||||
}
|
||||
|
||||
if (config.check_source) {
|
||||
xasprintf(&option_string, "%s--check-source ", option_string);
|
||||
}
|
||||
#else
|
||||
fping_prog = strdup(PATH_TO_FPING);
|
||||
#endif
|
||||
|
||||
char *command_line = NULL;
|
||||
xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
|
||||
|
||||
if (config.icmp_timestamp) {
|
||||
// no packet size settable for ICMP timestamp
|
||||
xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, server);
|
||||
} else {
|
||||
xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("%s\n", command_line);
|
||||
|
|
@ -268,13 +293,38 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
|
|||
|
||||
/* process command-line arguments */
|
||||
check_fping_config_wrapper process_arguments(int argc, char **argv) {
|
||||
static struct option longopts[] = {
|
||||
{"hostname", required_argument, 0, 'H'}, {"sourceip", required_argument, 0, 'S'}, {"sourceif", required_argument, 0, 'I'},
|
||||
{"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, {"alive", no_argument, 0, 'a'},
|
||||
{"bytes", required_argument, 0, 'b'}, {"number", required_argument, 0, 'n'}, {"target-timeout", required_argument, 0, 'T'},
|
||||
{"interval", required_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
|
||||
{"help", no_argument, 0, 'h'}, {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'},
|
||||
{"dontfrag", no_argument, 0, 'M'}, {"random", no_argument, 0, 'R'}, {0, 0, 0, 0}};
|
||||
enum {
|
||||
FWMARK_OPT = CHAR_MAX + 1,
|
||||
ICMP_TIMESTAMP_OPT,
|
||||
CHECK_SOURCE_OPT,
|
||||
};
|
||||
static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
|
||||
{"sourceip", required_argument, 0, 'S'},
|
||||
{"sourceif", required_argument, 0, 'I'},
|
||||
{"critical", required_argument, 0, 'c'},
|
||||
{"warning", required_argument, 0, 'w'},
|
||||
{"alive", no_argument, 0, 'a'},
|
||||
{"bytes", required_argument, 0, 'b'},
|
||||
{"number", required_argument, 0, 'n'},
|
||||
{"target-timeout", required_argument, 0, 'T'},
|
||||
{"interval", required_argument, 0, 'i'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"use-ipv4", no_argument, 0, '4'},
|
||||
{"use-ipv6", no_argument, 0, '6'},
|
||||
{"dontfrag", no_argument, 0, 'M'},
|
||||
{"random", no_argument, 0, 'R'},
|
||||
#ifdef FPING_VERSION_5_2_OR_HIGHER
|
||||
// only available with fping version >= 5.2
|
||||
{"fwmark", required_argument, NULL, FWMARK_OPT},
|
||||
# ifdef FPING_VERSION_5_3_OR_HIGHER
|
||||
// only available with fping version >= 5.3
|
||||
{"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
|
||||
{"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
|
||||
# endif
|
||||
#endif
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
char *rv[2];
|
||||
rv[PL] = NULL;
|
||||
|
|
@ -299,7 +349,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
|
|||
argc--;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
|
||||
|
||||
if (option_index == -1 || option_index == EOF || option_index == 1) {
|
||||
|
|
@ -340,11 +390,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
|
|||
address_family = AF_INET;
|
||||
break;
|
||||
case '6': /* IPv6 only */
|
||||
#ifdef USE_IPV6
|
||||
address_family = AF_INET6;
|
||||
#else
|
||||
usage(_("IPv6 support not available\n"));
|
||||
#endif
|
||||
break;
|
||||
case 'c':
|
||||
get_threshold(optarg, rv);
|
||||
|
|
@ -406,6 +452,20 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
|
|||
case 'M':
|
||||
result.config.dontfrag = true;
|
||||
break;
|
||||
case FWMARK_OPT:
|
||||
if (is_intpos(optarg)) {
|
||||
result.config.fwmark = (unsigned int)atol(optarg);
|
||||
result.config.fwmark_set = true;
|
||||
} else {
|
||||
usage(_("fwmark must be a positive integer"));
|
||||
}
|
||||
break;
|
||||
case ICMP_TIMESTAMP_OPT:
|
||||
result.config.icmp_timestamp = true;
|
||||
break;
|
||||
case CHECK_SOURCE_OPT:
|
||||
result.config.check_source = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -493,6 +553,16 @@ void print_help(void) {
|
|||
printf(" %s\n", _("set the Don't Fragment flag"));
|
||||
printf(" %s\n", "-R, --random");
|
||||
printf(" %s\n", _("random packet data (to foil link data compression)"));
|
||||
#ifdef FPING_VERSION_5_2_OR_HIGHER
|
||||
printf(" %s\n", "--fwmark=INTEGER");
|
||||
printf(" %s\n", _("set the routing mark to INTEGER (fping option)"));
|
||||
# ifdef FPING_VERSION_5_3_OR_HIGHER
|
||||
printf(" %s\n", "--icmp-timestamp");
|
||||
printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)"));
|
||||
printf(" %s\n", "--check-source");
|
||||
printf(" %s\n", _("discard replies not from target address (fping option)"));
|
||||
# endif
|
||||
#endif
|
||||
printf(UT_VERBOSE);
|
||||
printf("\n");
|
||||
printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,21 @@ typedef struct {
|
|||
bool cpl_p;
|
||||
int wpl;
|
||||
bool wpl_p;
|
||||
|
||||
// only available with fping version >= 5.2
|
||||
// for a given uint _fwmark_ fping sets _fwmark_ as a firewall mark
|
||||
// in the packets
|
||||
unsigned int fwmark;
|
||||
bool fwmark_set;
|
||||
|
||||
|
||||
// only available with fping version >= 5.3
|
||||
// Setting icmp_timestamp tells fping to use ICMP Timestamp (ICMP type 13) instead
|
||||
// of ICMP Echo
|
||||
bool icmp_timestamp;
|
||||
|
||||
// Setting check_source lets fping discard replies which are not from the target address
|
||||
bool check_source;
|
||||
} check_fping_config;
|
||||
|
||||
check_fping_config check_fping_config_init() {
|
||||
|
|
@ -53,6 +68,15 @@ check_fping_config check_fping_config_init() {
|
|||
.cpl_p = false,
|
||||
.wpl = 0,
|
||||
.wpl_p = false,
|
||||
|
||||
// only available with fping version >= 5.2
|
||||
.fwmark = 0,
|
||||
.fwmark_set = false, // just to be deterministic
|
||||
|
||||
// only available with fping version >= 5.3
|
||||
.icmp_timestamp = false,
|
||||
.check_source = false,
|
||||
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1724,6 +1724,16 @@ print_help (void)
|
|||
printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
|
||||
printf ("%s\n", _("certificate expiration times."));
|
||||
|
||||
printf ("\n");
|
||||
printf ("%s\n", _("ATTENTION!"));
|
||||
printf ("\n");
|
||||
printf ("%s\n", _("THIS PLUGIN IS DEPRECATED. The functionality was reimplemented by the"));
|
||||
printf ("%s\n", _("check_curl plugin, which can be used as a drop-in replacement. You should"));
|
||||
printf ("%s\n", _("migrate your checks over to check_curl, because check_http is going to be"));
|
||||
printf ("%s\n", _("removed sooner than later. Just replace check_http with check_curl in your"));
|
||||
printf ("%s\n", _("check command definitions."));
|
||||
printf ("%s\n", _("Report issues to: https://github.com/monitoring-plugins/monitoring-plugins/issues"));
|
||||
|
||||
printf ("\n\n");
|
||||
|
||||
print_usage ();
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ void print_usage(void);
|
|||
# include <sys/device.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/videoio.h> /* for __u8 and friends */
|
||||
# include <sys/scsiio.h>
|
||||
# include <sys/ataio.h>
|
||||
# include <dev/ata/atareg.h>
|
||||
|
|
@ -79,48 +78,47 @@ void print_usage(void);
|
|||
#define UNKNOWN -1
|
||||
|
||||
typedef struct threshold_s {
|
||||
__u8 id;
|
||||
__u8 threshold;
|
||||
__u8 reserved[10];
|
||||
uint8_t id;
|
||||
uint8_t threshold;
|
||||
uint8_t reserved[10];
|
||||
} __attribute__((packed)) threshold_t;
|
||||
|
||||
typedef struct thresholds_s {
|
||||
__u16 revision;
|
||||
uint16_t revision;
|
||||
threshold_t thresholds[NR_ATTRIBUTES];
|
||||
__u8 reserved[18];
|
||||
__u8 vendor[131];
|
||||
__u8 checksum;
|
||||
uint8_t reserved[18];
|
||||
uint8_t vendor[131];
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed)) thresholds_t;
|
||||
|
||||
typedef struct value_s {
|
||||
__u8 id;
|
||||
__u16 status;
|
||||
__u8 value;
|
||||
__u8 vendor[8];
|
||||
uint8_t id;
|
||||
uint16_t status;
|
||||
uint8_t value;
|
||||
uint8_t vendor[8];
|
||||
} __attribute__((packed)) value_t;
|
||||
|
||||
typedef struct values_s {
|
||||
__u16 revision;
|
||||
uint16_t revision;
|
||||
value_t values[NR_ATTRIBUTES];
|
||||
__u8 offline_status;
|
||||
__u8 vendor1;
|
||||
__u16 offline_timeout;
|
||||
__u8 vendor2;
|
||||
__u8 offline_capability;
|
||||
__u16 smart_capability;
|
||||
__u8 reserved[16];
|
||||
__u8 vendor[125];
|
||||
__u8 checksum;
|
||||
uint8_t offline_status;
|
||||
uint8_t vendor1;
|
||||
uint16_t offline_timeout;
|
||||
uint8_t vendor2;
|
||||
uint8_t offline_capability;
|
||||
uint16_t smart_capability;
|
||||
uint8_t reserved[16];
|
||||
uint8_t vendor[125];
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed)) values_t;
|
||||
|
||||
static struct {
|
||||
__u8 value;
|
||||
uint8_t value;
|
||||
char *text;
|
||||
} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"},
|
||||
{0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
|
||||
} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"}, {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
|
||||
|
||||
static struct {
|
||||
__u8 value;
|
||||
uint8_t value;
|
||||
char *text;
|
||||
} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
|
||||
{SMART_DISABLE, "SMART_DISABLE"},
|
||||
|
|
@ -140,7 +138,7 @@ static int smart_read_values(int, values_t *);
|
|||
static int nagios(values_t *, thresholds_t *);
|
||||
static void print_value(value_t *, threshold_t *);
|
||||
static void print_values(values_t *, thresholds_t *);
|
||||
static int smart_cmd_simple(int, enum SmartCommand, __u8, bool);
|
||||
static int smart_cmd_simple(int, enum SmartCommand, uint8_t, bool);
|
||||
static int smart_read_thresholds(int, thresholds_t *);
|
||||
static bool verbose = false;
|
||||
|
||||
|
|
@ -175,8 +173,9 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
o = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
|
||||
|
||||
if (o == -1 || o == EOF || o == 1)
|
||||
if (o == -1 || o == EOF || o == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case 'd':
|
||||
|
|
@ -234,8 +233,9 @@ int main(int argc, char *argv[]) {
|
|||
smart_read_values(fd, &values);
|
||||
smart_read_thresholds(fd, &thresholds);
|
||||
retval = nagios(&values, &thresholds);
|
||||
if (verbose)
|
||||
if (verbose) {
|
||||
print_values(&values, &thresholds);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return retval;
|
||||
|
|
@ -254,7 +254,7 @@ char *get_offline_text(int status) {
|
|||
int smart_read_values(int fd, values_t *values) {
|
||||
#ifdef __linux__
|
||||
int e;
|
||||
__u8 args[4 + 512];
|
||||
uint8_t args[4 + 512];
|
||||
args[0] = WIN_SMART;
|
||||
args[1] = 0;
|
||||
args[2] = SMART_READ_VALUES;
|
||||
|
|
@ -282,8 +282,9 @@ int smart_read_values(int fd, values_t *values) {
|
|||
req.cylinder = WDSMART_CYL;
|
||||
|
||||
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
|
||||
if (req.retsts != ATACMD_OK)
|
||||
if (req.retsts != ATACMD_OK) {
|
||||
errno = ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
|
|
@ -370,22 +371,24 @@ void print_values(values_t *p, thresholds_t *t) {
|
|||
p->smart_capability & 1 ? "SaveOnStandBy" : "", p->smart_capability & 2 ? "AutoSave" : "");
|
||||
}
|
||||
|
||||
int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_error) {
|
||||
int smart_cmd_simple(int fd, enum SmartCommand command, uint8_t val0, bool show_error) {
|
||||
int e = STATE_UNKNOWN;
|
||||
#ifdef __linux__
|
||||
__u8 args[4];
|
||||
uint8_t args[4];
|
||||
args[0] = WIN_SMART;
|
||||
args[1] = val0;
|
||||
args[2] = smart_command[command].value;
|
||||
args[3] = 0;
|
||||
if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
|
||||
e = STATE_CRITICAL;
|
||||
if (show_error)
|
||||
if (show_error) {
|
||||
printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
e = STATE_OK;
|
||||
if (show_error)
|
||||
if (show_error) {
|
||||
printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
|
@ -401,20 +404,24 @@ int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_err
|
|||
req.sec_count = val0;
|
||||
|
||||
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
|
||||
if (req.retsts != ATACMD_OK)
|
||||
if (req.retsts != ATACMD_OK) {
|
||||
errno = ENODEV;
|
||||
if (req.cylinder != WDSMART_CYL)
|
||||
}
|
||||
if (req.cylinder != WDSMART_CYL) {
|
||||
errno = ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
e = STATE_CRITICAL;
|
||||
if (show_error)
|
||||
if (show_error) {
|
||||
printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
e = STATE_OK;
|
||||
if (show_error)
|
||||
if (show_error) {
|
||||
printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __NetBSD__ */
|
||||
|
|
@ -424,7 +431,7 @@ int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_err
|
|||
int smart_read_thresholds(int fd, thresholds_t *thresholds) {
|
||||
#ifdef __linux__
|
||||
int e;
|
||||
__u8 args[4 + 512];
|
||||
uint8_t args[4 + 512];
|
||||
args[0] = WIN_SMART;
|
||||
args[1] = 0;
|
||||
args[2] = SMART_READ_THRESHOLDS;
|
||||
|
|
@ -452,8 +459,9 @@ int smart_read_thresholds(int fd, thresholds_t *thresholds) {
|
|||
req.cylinder = WDSMART_CYL;
|
||||
|
||||
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
|
||||
if (req.retsts != ATACMD_OK)
|
||||
if (req.retsts != ATACMD_OK) {
|
||||
errno = ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -116,10 +116,10 @@ int main(int argc, char **argv) {
|
|||
# ifdef PING_HAS_TIMEOUT
|
||||
xasprintf(&cmd, rawcmd, timeout_interval, config.max_packets, config.addresses[i]);
|
||||
# else
|
||||
xasprintf(&cmd, rawcmd, config.max_packets, addresses[i]);
|
||||
xasprintf(&cmd, rawcmd, config.max_packets, config.addresses[i]);
|
||||
# endif
|
||||
#else
|
||||
xasprintf(&cmd, rawcmd, addresses[i], config.max_packets);
|
||||
xasprintf(&cmd, rawcmd, config.addresses[i], config.max_packets);
|
||||
#endif
|
||||
|
||||
if (verbose >= 2) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
75
plugins/check_procs.d/config.h
Normal file
75
plugins/check_procs.d/config.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../config.h"
|
||||
#include "regex.h"
|
||||
#include "thresholds.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
enum metric {
|
||||
METRIC_PROCS,
|
||||
METRIC_VSZ,
|
||||
METRIC_RSS,
|
||||
METRIC_CPU,
|
||||
METRIC_ELAPSED
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int options; /* bitmask of filter criteria to test against */
|
||||
enum metric metric;
|
||||
char *metric_name;
|
||||
char *input_filename;
|
||||
char *prog;
|
||||
char *args;
|
||||
char *fmt;
|
||||
char *fails;
|
||||
char *exclude_progs;
|
||||
char **exclude_progs_arr;
|
||||
char exclude_progs_counter;
|
||||
regex_t re_args;
|
||||
|
||||
bool kthread_filter;
|
||||
bool usepid; /* whether to test for pid or /proc/pid/exe */
|
||||
uid_t uid;
|
||||
pid_t ppid;
|
||||
int vsz;
|
||||
int rss;
|
||||
float pcpu;
|
||||
char *statopts;
|
||||
|
||||
char *warning_range;
|
||||
char *critical_range;
|
||||
thresholds *procs_thresholds;
|
||||
} check_procs_config;
|
||||
|
||||
check_procs_config check_procs_config_init() {
|
||||
check_procs_config tmp = {
|
||||
.options = 0,
|
||||
.metric = METRIC_PROCS,
|
||||
.metric_name = strdup("PROCS"),
|
||||
.input_filename = NULL,
|
||||
.prog = NULL,
|
||||
.args = NULL,
|
||||
.fmt = NULL,
|
||||
.fails = NULL,
|
||||
.exclude_progs = NULL,
|
||||
.exclude_progs_arr = NULL,
|
||||
.exclude_progs_counter = 0,
|
||||
.re_args = {0},
|
||||
|
||||
.kthread_filter = false,
|
||||
.usepid = false,
|
||||
.uid = 0,
|
||||
.ppid = 0,
|
||||
.vsz = 0,
|
||||
.rss = 0,
|
||||
.pcpu = 0,
|
||||
.statopts = NULL,
|
||||
|
||||
.warning_range = NULL,
|
||||
.critical_range = NULL,
|
||||
.procs_thresholds = NULL,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -90,6 +90,14 @@ int main(int argc, char **argv) {
|
|||
exit(STATE_UNKNOWN);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("Swap retrieval result:\n"
|
||||
"\tFree: %llu\n"
|
||||
"\tUsed: %llu\n"
|
||||
"\tTotal: %llu\n",
|
||||
data.metrics.free, data.metrics.used, data.metrics.total);
|
||||
}
|
||||
|
||||
double percent_used;
|
||||
mp_check overall = mp_check_init();
|
||||
if (config.output_format_is_set) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
#include "output.h"
|
||||
#include "../../lib/output.h"
|
||||
#include "../../lib/states.h"
|
||||
|
||||
#ifndef SWAP_CONVERSION
|
||||
# define SWAP_CONVERSION 1
|
||||
|
|
@ -26,7 +27,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
bool allswaps;
|
||||
int no_swap_state;
|
||||
mp_state_enum no_swap_state;
|
||||
bool warn_is_set;
|
||||
check_swap_threshold warn;
|
||||
bool crit_is_set;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ swap_result getSwapFromProcMeminfo(char proc_meminfo[]) {
|
|||
FILE *meminfo_file_ptr;
|
||||
meminfo_file_ptr = fopen(proc_meminfo, "r");
|
||||
|
||||
swap_result result = {0};
|
||||
swap_result result = {};
|
||||
result.errorcode = STATE_UNKNOWN;
|
||||
|
||||
if (meminfo_file_ptr == NULL) {
|
||||
|
|
@ -78,83 +78,71 @@ swap_result getSwapFromProcMeminfo(char proc_meminfo[]) {
|
|||
return result;
|
||||
}
|
||||
|
||||
uint64_t swap_total = 0;
|
||||
uint64_t swap_used = 0;
|
||||
uint64_t swap_free = 0;
|
||||
unsigned long swap_total = 0;
|
||||
unsigned long swap_used = 0;
|
||||
unsigned long swap_free = 0;
|
||||
|
||||
bool found_total = false;
|
||||
bool found_used = false;
|
||||
bool found_free = false;
|
||||
|
||||
char input_buffer[MAX_INPUT_BUFFER];
|
||||
char str[32];
|
||||
|
||||
while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, meminfo_file_ptr)) {
|
||||
uint64_t tmp_KB = 0;
|
||||
|
||||
/*
|
||||
* The following sscanf call looks for a line looking like: "Swap: 123
|
||||
* 123 123" On which kind of system this format exists, I can not say,
|
||||
* but I wanted to document this for people who are not adapt with
|
||||
* sscanf anymore, like me
|
||||
* Also the units used here are unclear and probably wrong
|
||||
* 123 123" which exists on NetBSD (at least),
|
||||
* The unit should be Bytes
|
||||
*/
|
||||
if (sscanf(input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %lu %lu %lu", &swap_total, &swap_used, &swap_free) == 3) {
|
||||
|
||||
result.metrics.total += swap_total;
|
||||
result.metrics.used += swap_used;
|
||||
result.metrics.free += swap_free;
|
||||
|
||||
found_total = true;
|
||||
found_free = true;
|
||||
found_used = true;
|
||||
|
||||
// Set error
|
||||
result.errorcode = STATE_OK;
|
||||
// Break out of fgets here, since both scanf expressions might match (NetBSD for example)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following sscanf call looks for lines looking like:
|
||||
* "SwapTotal: 123" and "SwapFree: 123" This format exists at least
|
||||
* on Debian Linux with a 5.* kernel
|
||||
*/
|
||||
} else {
|
||||
int sscanf_result = sscanf(input_buffer,
|
||||
"%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %lu "
|
||||
"%*[k]%*[B]",
|
||||
str, &tmp_KB);
|
||||
/*
|
||||
* The following sscanf call looks for lines looking like:
|
||||
* "SwapTotal: 123" and "SwapFree: 123" This format exists at least
|
||||
* on Debian Linux with a 5.* kernel
|
||||
*/
|
||||
unsigned long tmp_KB = 0;
|
||||
int sscanf_result = sscanf(input_buffer,
|
||||
"%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %lu "
|
||||
"%*[k]%*[B]",
|
||||
str, &tmp_KB);
|
||||
|
||||
if (sscanf_result == 2) {
|
||||
if (sscanf_result == 2) {
|
||||
|
||||
if (verbose >= 3) {
|
||||
printf("Got %s with %lu\n", str, tmp_KB);
|
||||
}
|
||||
|
||||
/* I think this part is always in Kb, so convert to bytes */
|
||||
if (strcmp("Total", str) == 0) {
|
||||
swap_total = tmp_KB * 1000;
|
||||
found_total = true;
|
||||
} else if (strcmp("Free", str) == 0) {
|
||||
swap_free = swap_free + tmp_KB * 1000;
|
||||
found_free = true;
|
||||
found_used = true; // No explicit used metric available
|
||||
} else if (strcmp("Cached", str) == 0) {
|
||||
swap_free = swap_free + tmp_KB * 1000;
|
||||
found_free = true;
|
||||
found_used = true; // No explicit used metric available
|
||||
}
|
||||
|
||||
result.errorcode = STATE_OK;
|
||||
if (verbose >= 3) {
|
||||
printf("Got %s with %lu\n", str, tmp_KB);
|
||||
}
|
||||
|
||||
/* I think this part is always in Kb, so convert to bytes */
|
||||
if (strcmp("Total", str) == 0) {
|
||||
swap_total = tmp_KB * 1000;
|
||||
found_total = true;
|
||||
} else if (strcmp("Free", str) == 0) {
|
||||
swap_free += tmp_KB * 1000;
|
||||
found_free = true;
|
||||
} else if (strcmp("Cached", str) == 0) {
|
||||
swap_free += tmp_KB * 1000;
|
||||
}
|
||||
|
||||
result.errorcode = STATE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(meminfo_file_ptr);
|
||||
|
||||
result.metrics.total = swap_total;
|
||||
result.metrics.used = swap_total - swap_free;
|
||||
result.metrics.free = swap_free;
|
||||
result.metrics.used = swap_total - swap_free;
|
||||
|
||||
if (!found_free || !found_total || !found_used) {
|
||||
if (!found_free || !found_total) {
|
||||
result.errorcode = STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
|
@ -297,8 +285,14 @@ struct swapent {
|
|||
};
|
||||
|
||||
#else
|
||||
|
||||
// Includes for NetBSD
|
||||
# include <unistd.h>
|
||||
# include <sys/swap.h>
|
||||
|
||||
# define bsd_swapctl swapctl
|
||||
#endif
|
||||
|
||||
#endif // CHECK_SWAP_SWAPCTL_BSD
|
||||
|
||||
swap_result getSwapFromSwapctl_BSD(swap_config config) {
|
||||
/* get the number of active swap devices */
|
||||
|
|
@ -322,8 +316,8 @@ swap_result getSwapFromSwapctl_BSD(swap_config config) {
|
|||
unsigned long long used_swap_mb = 0;
|
||||
|
||||
for (int i = 0; i < nswaps; i++) {
|
||||
dsktotal_mb = (float)ent[i].se_nblks / (float)config.conversion_factor;
|
||||
dskused_mb = (float)ent[i].se_inuse / (float)config.conversion_factor;
|
||||
dsktotal_mb = (double)ent[i].se_nblks / (double)config.conversion_factor;
|
||||
dskused_mb = (double)ent[i].se_inuse / (double)config.conversion_factor;
|
||||
dskfree_mb = (dsktotal_mb - dskused_mb);
|
||||
|
||||
if (config.allswaps && dsktotal_mb > 0) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "../config.h"
|
||||
#include "../lib/monitoringplug.h"
|
||||
|
||||
#ifdef HAVE_FEATURES_H
|
||||
|
|
@ -110,7 +110,7 @@
|
|||
|
||||
/* GNU Libraries */
|
||||
#include <getopt.h>
|
||||
#include "dirname.h"
|
||||
#include "../gl/dirname.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ enum {
|
|||
* Internationalization
|
||||
*
|
||||
*/
|
||||
#include "gettext.h"
|
||||
#include "../gl/gettext.h"
|
||||
#define _(String) gettext (String)
|
||||
#if ! ENABLE_NLS
|
||||
# undef textdomain
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
|
|||
time_t tm_t;
|
||||
|
||||
if (!certificate) {
|
||||
printf("%s\n", _("CRITICAL - Cannot retrieve server certificate."));
|
||||
printf("%s\n", _("CRITICAL - No server certificate present to inspect."));
|
||||
return STATE_CRITICAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use strict;
|
|||
use Test::More;
|
||||
use NPTest;
|
||||
use POSIX qw(ceil floor);
|
||||
use Data::Dumper;
|
||||
|
||||
my $successOutput = '/^DISK OK/';
|
||||
my $failureOutput = '/^DISK CRITICAL/';
|
||||
|
|
@ -20,173 +21,216 @@ my $result;
|
|||
my $mountpoint_valid = getTestParameter( "NP_MOUNTPOINT_VALID", "Path to valid mountpoint", "/");
|
||||
my $mountpoint2_valid = getTestParameter( "NP_MOUNTPOINT2_VALID", "Path to another valid mountpoint. Must be different from 1st one", "/var");
|
||||
|
||||
my $output_format = "--output-format mp-test-json";
|
||||
|
||||
if ($mountpoint_valid eq "" or $mountpoint2_valid eq "") {
|
||||
plan skip_all => "Need 2 mountpoints to test";
|
||||
} else {
|
||||
plan tests => 94;
|
||||
plan tests => 97;
|
||||
}
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w 1% -c 1% -p $mountpoint_valid -w 1% -c 1% -p $mountpoint2_valid"
|
||||
"./check_disk -w 1% -c 1% -p $mountpoint_valid -w 1% -c 1% -P -p $mountpoint2_valid $output_format"
|
||||
);
|
||||
cmp_ok( $result->return_code, "==", 0, "Checking two mountpoints (must have at least 1% free in space and inodes)");
|
||||
my $c = 0;
|
||||
$_ = $result->output;
|
||||
$c++ while /\(/g; # counts number of "(" - should be two
|
||||
cmp_ok( $c, '==', 2, "Got two mountpoints in output");
|
||||
|
||||
like($result->{'mp_test_result'}->{'state'}, "/OK/", "Main result is OK");
|
||||
like($result->{'mp_test_result'}->{'checks'}->[0]->{'state'}, "/OK/", "First sub result is OK");
|
||||
like($result->{'mp_test_result'}->{'checks'}->[1]->{'state'}, "/OK/", "Second sub result is OK");
|
||||
|
||||
# Get perf data
|
||||
# Should use Monitoring::Plugin
|
||||
my @perf_data = sort(split(/ /, $result->perf_output));
|
||||
my $absolut_space_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
# print("absolute space on mp1: ". $absolut_space_mp1 . "\n");
|
||||
|
||||
my $free_percent_on_mp1 = ($result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'} / ($absolut_space_mp1/100));
|
||||
print("free percent on mp1: ". $free_percent_on_mp1 . "\n");
|
||||
|
||||
my $absolut_space_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
# print("absolute space on mp2: ". $absolut_space_mp2 . "\n");
|
||||
|
||||
my $free_percent_on_mp2 = ($result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'}/ ($absolut_space_mp2/100));
|
||||
print("free percent on mp2: ". $free_percent_on_mp2 . "\n");
|
||||
|
||||
my @perfdata;
|
||||
@perfdata[0] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
|
||||
@perfdata[1] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
|
||||
|
||||
# Decrease precision of numbers since the the fs might be modified between the two runs
|
||||
$perfdata[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
|
||||
$perfdata[1]->{'value'}->{'value'} = int($perfdata[1]->{'value'}->{'value'} / 1000000);
|
||||
|
||||
# Calculate avg_free free on mountpoint1 and mountpoint2
|
||||
# because if you check in the middle, you should get different errors
|
||||
$_ = $result->output;
|
||||
my ($free_on_mp1, $free_on_mp2) = (m/\((\d+\.\d+)%.*\((\d+\.\d+)%/);
|
||||
die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2);
|
||||
my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2);
|
||||
my $avg_free_percent = ceil(($free_percent_on_mp1+$free_percent_on_mp2)/2);
|
||||
# print("avg_free: " . $avg_free_percent . "\n");
|
||||
my ($more_free, $less_free);
|
||||
if ($free_on_mp1 > $free_on_mp2) {
|
||||
if ($free_percent_on_mp1 > $free_percent_on_mp2) {
|
||||
$more_free = $mountpoint_valid;
|
||||
$less_free = $mountpoint2_valid;
|
||||
} elsif ($free_on_mp1 < $free_on_mp2) {
|
||||
} elsif ($free_percent_on_mp1 < $free_percent_on_mp2) {
|
||||
$more_free = $mountpoint2_valid;
|
||||
$less_free = $mountpoint_valid;
|
||||
} else {
|
||||
die "Two mountpoints are the same - cannot do rest of test";
|
||||
}
|
||||
if($free_on_mp1 == $avg_free || $free_on_mp2 == $avg_free) {
|
||||
|
||||
print("less free: " . $less_free . "\n");
|
||||
print("more free: " . $more_free . "\n");
|
||||
|
||||
if($free_percent_on_mp1 == $avg_free_percent || $free_percent_on_mp2 == $avg_free_percent) {
|
||||
die "One mountpoints has average space free - cannot do rest of test";
|
||||
}
|
||||
|
||||
my $free_inodes_on_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}[2]->{'perfdata'}->[0]->{'value'}->{'value'};
|
||||
my $total_inodes_on_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}[2]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
my $free_inode_percentage_on_mp1 = $free_inodes_on_mp1 / ($total_inodes_on_mp1 / 100);
|
||||
|
||||
# Do same for inodes
|
||||
$_ = $result->output;
|
||||
my ($free_inode_on_mp1, $free_inode_on_mp2) = (m/inode=(\d+)%.*inode=(\d+)%/);
|
||||
die "Cannot parse free inodes: $_" unless ($free_inode_on_mp1 && $free_inode_on_mp2);
|
||||
my $avg_inode_free = ceil(($free_inode_on_mp1 + $free_inode_on_mp2)/2);
|
||||
my $free_inodes_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[2]->{'perfdata'}->[0]->{'value'}->{'value'};
|
||||
my $total_inodes_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[2]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
my $free_inode_percentage_on_mp2 = $free_inodes_on_mp2 / ($total_inodes_on_mp2 / 100);
|
||||
|
||||
my $avg_inode_free_percentage = ceil(($free_inode_percentage_on_mp1 + $free_inode_percentage_on_mp2)/2);
|
||||
my ($more_inode_free, $less_inode_free);
|
||||
if ($free_inode_on_mp1 > $free_inode_on_mp2) {
|
||||
if ($free_inode_percentage_on_mp1 > $free_inode_percentage_on_mp2) {
|
||||
$more_inode_free = $mountpoint_valid;
|
||||
$less_inode_free = $mountpoint2_valid;
|
||||
} elsif ($free_inode_on_mp1 < $free_inode_on_mp2) {
|
||||
} elsif ($free_inode_percentage_on_mp1 < $free_inode_percentage_on_mp2) {
|
||||
$more_inode_free = $mountpoint2_valid;
|
||||
$less_inode_free = $mountpoint_valid;
|
||||
} else {
|
||||
die "Two mountpoints with same inodes free - cannot do rest of test";
|
||||
}
|
||||
if($free_inode_on_mp1 == $avg_inode_free || $free_inode_on_mp2 == $avg_inode_free) {
|
||||
if($free_inode_percentage_on_mp1 == $avg_inode_free_percentage || $free_inode_percentage_on_mp2 == $avg_inode_free_percentage) {
|
||||
die "One mountpoints has average inodes free - cannot do rest of test";
|
||||
}
|
||||
|
||||
# Verify performance data
|
||||
# First check absolute thresholds...
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w 20 -c 10 -p $mountpoint_valid"
|
||||
"./check_disk -w 20 -c 10 -p $mountpoint_valid $output_format"
|
||||
);
|
||||
$_ = $result->perf_output;
|
||||
my ($warn_absth_data, $crit_absth_data, $total_absth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
|
||||
# default unit is MiB, but perfdata is always bytes
|
||||
is ($warn_absth_data, $total_absth_data - (20 * (2 ** 20)), "Wrong warning in perf data using absolute thresholds");
|
||||
is ($crit_absth_data, $total_absth_data - (10 * (2 ** 20)), "Wrong critical in perf data using absolute thresholds");
|
||||
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
|
||||
my $warn_absth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'warn'}->{'end'}->{'value'};
|
||||
my $crit_absth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'crit'}->{'end'}->{'value'};
|
||||
my $total_absth_data= $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
|
||||
# print("warn: " .$warn_absth_data . "\n");
|
||||
# print("crit: " .$crit_absth_data . "\n");
|
||||
# print("total: " .$total_absth_data . "\n");
|
||||
|
||||
is ($warn_absth_data <=> (20 * (2 ** 20)), 0, "Wrong warning in perf data using absolute thresholds");
|
||||
is ($crit_absth_data <=> (10 * (2 ** 20)), 0, "Wrong critical in perf data using absolute thresholds");
|
||||
|
||||
# Then check percent thresholds.
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w 20% -c 10% -p $mountpoint_valid"
|
||||
"./check_disk -w 20% -c 10% -p $mountpoint_valid $output_format"
|
||||
);
|
||||
$_ = $result->perf_output;
|
||||
my ($warn_percth_data, $crit_percth_data, $total_percth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
|
||||
is ($warn_percth_data, int((1-20/100)*$total_percth_data), "Wrong warning in perf data using percent thresholds");
|
||||
is ($crit_percth_data, int((1-10/100)*$total_percth_data), "Wrong critical in perf data using percent thresholds");
|
||||
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
|
||||
my $warn_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'warn'}->{'end'}->{'value'};
|
||||
my $crit_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'crit'}->{'end'}->{'value'};
|
||||
my $total_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'max'}->{'value'};
|
||||
|
||||
print("warn_percth_data: " . $warn_percth_data . "\n");
|
||||
print("crit_percth_data: " . $crit_percth_data . "\n");
|
||||
|
||||
is (int($warn_percth_data), int((20/100)*$total_percth_data), "Wrong warning in perf data using percent thresholds. Got " . $warn_percth_data . " with total " . $total_percth_data);
|
||||
is (int($crit_percth_data), int((10/100)*$total_percth_data), "Wrong critical in perf data using percent thresholds. Got " . $crit_percth_data . " with total " . $total_percth_data);
|
||||
|
||||
|
||||
# Check when order of mount points are reversed, that perf data remains same
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w 1% -c 1% -p $mountpoint2_valid -w 1% -c 1% -p $mountpoint_valid"
|
||||
"./check_disk -w 1% -c 1% -p $mountpoint2_valid -w 1% -c 1% -p $mountpoint_valid $output_format"
|
||||
);
|
||||
@_ = sort(split(/ /, $result->perf_output));
|
||||
is_deeply( \@perf_data, \@_, "perf data for both filesystems same when reversed");
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
|
||||
# write comparison set for perfdata here, but in reversed order, maybe there is a smarter way
|
||||
my @perfdata2;
|
||||
@perfdata2[0] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
|
||||
@perfdata2[1] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
|
||||
# Decrease precision of numbers since the the fs might be modified between the two runs
|
||||
$perfdata2[0]->{'value'}->{'value'} = int($perfdata2[0]->{'value'}->{'value'} / 1000000);
|
||||
$perfdata2[1]->{'value'}->{'value'} = int($perfdata2[1]->{'value'}->{'value'} / 1000000);
|
||||
is_deeply(\@perfdata, \@perfdata2, "perf data for both filesystems same when reversed");
|
||||
|
||||
# Basic filesystem checks for sizes
|
||||
$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free" );
|
||||
cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free");
|
||||
like ( $result->output, $successOutput, "OK output" );
|
||||
like ( $result->only_output, qr/free space/, "Have free space text");
|
||||
like ( $result->only_output, qr/$more_free/, "Have disk name in text");
|
||||
$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free $output_format");
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
like($result->{'mp_test_result'}->{'state'}, "/OK/", "At least 1 MB available on $more_free");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" );
|
||||
cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free");
|
||||
$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free $output_format" );
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
like($result->{'mp_test_result'}->{'state'}, "/OK/", "At least 1 MB available on $more_free and $less_free");
|
||||
|
||||
$_ = $result->output;
|
||||
|
||||
my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g);
|
||||
my $free_mb_on_mp1 =$result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'} / (1024 * 1024);
|
||||
my $free_mb_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'}/ (1024 * 1024);
|
||||
die "Cannot parse output: $_" unless ($free_mb_on_mp1 && $free_mb_on_mp2);
|
||||
|
||||
my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
|
||||
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free $output_format" );
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free" );
|
||||
is( $result->only_output, "DISK OK", "No print out of disks with -e for OKs");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk 100 100 $more_free" );
|
||||
cmp_ok( $result->return_code, '==', 0, "Old syntax okay" );
|
||||
$result = NPTest->testCmd( "./check_disk 101 101 $more_free" );
|
||||
like($result->output, "/OK/", "OK in Output");
|
||||
cmp_ok( $result->return_code, '==', 0, "Old syntax okay, output was: ". $result->output . "\n" );
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -w 1% -c 1% -p $more_free" );
|
||||
cmp_ok( $result->return_code, "==", 0, "At least 1% free" );
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w 1% -c 1% -p $more_free -w 100% -c 100% -p $less_free"
|
||||
"./check_disk -w 1% -c 1% -p $more_free -w 100% -c 100% -p $less_free $output_format"
|
||||
);
|
||||
cmp_ok( $result->return_code, "==", 2, "Get critical on less_free mountpoint $less_free" );
|
||||
like( $result->output, $failureOutput, "Right output" );
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
like($result->{'mp_test_result'}->{'state'}, "/CRITICAL/", "Get critical on less_free mountpoint $less_free");
|
||||
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c 0% -p $less_free"
|
||||
"./check_disk -w $avg_free_percent% -c 0% -p $less_free $output_format"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 1, "Get warning on less_free mountpoint, when checking avg_free");
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
like($result->{'mp_test_result'}->{'state'}, "/WARNING/", "Get warning on less_free mountpoint, when checking avg_free");
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c $avg_free% -p $more_free"
|
||||
"./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, when checking avg_free");
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
|
||||
"./check_disk -w $avg_free_percent% -c 0% -p $less_free -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, "==", 1, "Combining above two tests, get warning");
|
||||
my $all_disks = $result->output;
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -e -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
|
||||
"./check_disk -e -w $avg_free_percent% -c 0% -p $less_free -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
|
||||
);
|
||||
isnt( $result->output, $all_disks, "-e gives different output");
|
||||
|
||||
# Need spaces around filesystem name in case less_free and more_free are nested
|
||||
like( $result->output, qr/ $less_free /, "Found problem $less_free");
|
||||
unlike( $result->only_output, qr/ $more_free /, "Has ignored $more_free as not a problem");
|
||||
like( $result->perf_output, qr/ $more_free=/, "But $more_free is still in perf data");
|
||||
like( $result->perf_output, qr/'$more_free'=/, "But $more_free is still in perf data");
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c 0% -p $more_free"
|
||||
"./check_disk -w $avg_free_percent% -c 0% -p $more_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, checking avg_free");
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c $avg_free% -p $less_free"
|
||||
"./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $less_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 2, "Get critical on less_free, checking avg_free");
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c 0% -p $more_free -w $avg_free% -c $avg_free% -p $less_free"
|
||||
"./check_disk -w $avg_free_percent% -c 0% -p $more_free -w $avg_free_percent% -c $avg_free_percent% -p $less_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 2, "Combining above two tests, get critical");
|
||||
|
||||
$result = NPTest->testCmd(
|
||||
"./check_disk -w $avg_free% -c $avg_free% -p $less_free -w $avg_free% -c 0% -p $more_free"
|
||||
"./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $less_free -w $avg_free_percent% -c 0% -p $more_free"
|
||||
);
|
||||
cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
|
||||
|
||||
|
|
@ -203,32 +247,32 @@ is( $result->return_code, 2, "Critical requesting 100% free inodes for both moun
|
|||
$result = NPTest->testCmd( "./check_disk --iwarning 1% --icritical 1% -p $more_inode_free -K 100% -W 100% -p $less_inode_free" );
|
||||
is( $result->return_code, 2, "Get critical on less_inode_free mountpoint $less_inode_free");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $less_inode_free" );
|
||||
is( $result->return_code, 1, "Get warning on less_inode_free, when checking average");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free ");
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free ");
|
||||
is( $result->return_code, 0, "Get ok on more_inode_free when checking average");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $less_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free" );
|
||||
is ($result->return_code, 1, "Combine above two tests, get warning");
|
||||
$all_disks = $result->output;
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -e -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -e -W $avg_inode_free_percentage% -K 0% -p $less_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free" );
|
||||
isnt( $result->output, $all_disks, "-e gives different output");
|
||||
like( $result->output, qr/$less_inode_free/, "Found problem $less_inode_free");
|
||||
unlike( $result->only_output, qr/$more_inode_free\s/, "Has ignored $more_inode_free as not a problem");
|
||||
like( $result->perf_output, qr/$more_inode_free/, "But $more_inode_free is still in perf data");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $more_inode_free" );
|
||||
is( $result->return_code, 0, "Get ok on more_inode_free mountpoint, checking average");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free" );
|
||||
is( $result->return_code, 2, "Get critical on less_inode_free, checking average");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $more_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free" );
|
||||
is( $result->return_code, 2, "Combining above two tests, get critical");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free -W $avg_inode_free% -K 0% -p $more_inode_free" );
|
||||
$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free -W $avg_inode_free_percentage% -K 0% -p $more_inode_free" );
|
||||
cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
|
||||
|
||||
|
||||
|
|
@ -249,9 +293,9 @@ $result = NPTest->testCmd(
|
|||
);
|
||||
cmp_ok( $result->return_code, "==", 3, "Invalid options: -p must come after thresholds" );
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -w 100% -c 100% ".${mountpoint_valid} ); # 100% empty
|
||||
cmp_ok( $result->return_code, "==", 2, "100% empty" );
|
||||
like( $result->output, $failureOutput, "Right output" );
|
||||
$result = NPTest->testCmd( "./check_disk -w 100% -c 100% $output_format ".${mountpoint_valid} ); # 100% empty
|
||||
cmp_ok( $result->return_code, "==", 0, "100% empty" );
|
||||
like($result->{'mp_test_result'}->{'state'}, "/CRITICAL/", "100% empty");
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk -w 100000000 -c 100000000 $mountpoint_valid" );
|
||||
cmp_ok( $result->return_code, '==', 2, "Check for 100TB free" );
|
||||
|
|
@ -263,7 +307,8 @@ cmp_ok( $result->return_code, "==", 2, "100 TB empty" );
|
|||
# Checking old syntax of check_disk warn crit [fs], with warn/crit at USED% thresholds
|
||||
$result = NPTest->testCmd( "./check_disk 0 0 ".${mountpoint_valid} );
|
||||
cmp_ok( $result->return_code, "==", 2, "Old syntax: 0% used");
|
||||
like ( $result->only_output, qr(^[^;]*;[^;]*$), "Select only one path with positional arguments");
|
||||
# like ( $result->only_output, qr(^[^;]*;[^;]*$), "Select only one path with positional arguments");
|
||||
# TODO not sure what the above should test, taking it out
|
||||
|
||||
$result = NPTest->testCmd( "./check_disk 100 100 $mountpoint_valid" );
|
||||
cmp_ok( $result->return_code, '==', 0, "Old syntax: 100% used" );
|
||||
|
|
@ -311,8 +356,9 @@ $result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p / -p /" );
|
|||
unlike( $result->output, '/ \/ .* \/ /', "Should not show same filesystem twice");
|
||||
|
||||
# are partitions added if -C is given without path selection -p ?
|
||||
$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoint_valid" );
|
||||
like( $result->output, '/;.*;\|/', "-C selects partitions if -p is not given");
|
||||
$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoint_valid $output_format" );
|
||||
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
|
||||
cmp_ok(scalar $result->{'mp_test_result'}->{'checks'}, '>', 1, "-C invokes matchall logic again");
|
||||
|
||||
# grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit
|
||||
$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all + 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
|
||||
|
|
@ -359,39 +405,37 @@ like( $result->output, qr/$mountpoint2_valid/,"ignore: output data does have $mo
|
|||
# ignore-missing: exit okay, when fs is not accessible
|
||||
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p /bob");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for not existing filesystem /bob");
|
||||
like( $result->output, '/^DISK OK - No disks were found for provided parameters - ignored paths: /bob;.*$/', 'Output OK');
|
||||
like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when regex does not match
|
||||
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r /bob");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK - No disks were found for provided parameters.*$/', 'Output OK');
|
||||
like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when fs with exact match (-E) is not found
|
||||
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -E -p /etc");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay when exact match does not find fs");
|
||||
like( $result->output, '/^DISK OK - No disks were found for provided parameters - ignored paths: /etc;.*$/', 'Output OK');
|
||||
like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (regex)
|
||||
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r '/bob' -r '^/\$'");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK - free space: \/ .*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (path)
|
||||
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p '/bob' -p '/'");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK - free space: / .*; - ignored paths: /bob;.*$/', 'Output OK');
|
||||
# like( $result->output, '/^DISK OK - free space: / .*; - ignored paths: /bob;.*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when checking one non-existing fs (path) and one ignored
|
||||
$result = NPTest->testCmd( "./check_disk -n -w 0% -c 0% -r /dummy -i /dummy2");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK - No disks were found for provided parameters\|$/', 'Output OK');
|
||||
like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when regex match does not find anything
|
||||
$result = NPTest->testCmd( "./check_disk -n -e -l -w 10% -c 5% -W 10% -K 5% -r /dummy");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK\|$/', 'Output OK');
|
||||
|
||||
# ignore-missing: exit okay, when regex match does not find anything
|
||||
$result = NPTest->testCmd( "./check_disk -n -l -w 10% -c 5% -W 10% -K 5% -r /dummy");
|
||||
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
|
||||
like( $result->output, '/^DISK OK - No disks were found for provided parameters\|$/', 'Output OK');
|
||||
like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
|
||||
|
|
|
|||
|
|
@ -17,28 +17,16 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
#include "utils_disk.h"
|
||||
#include "tap.h"
|
||||
#include "../check_disk.d/utils_disk.h"
|
||||
#include "../../tap/tap.h"
|
||||
#include "regex.h"
|
||||
|
||||
void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
plan_tests(35);
|
||||
|
||||
struct name_list *exclude_filesystem = NULL;
|
||||
struct name_list *exclude_fstype = NULL;
|
||||
struct name_list *dummy_mountlist = NULL;
|
||||
struct name_list *temp_name;
|
||||
struct parameter_list *paths = NULL;
|
||||
struct parameter_list *p, *prev = NULL, *last = NULL;
|
||||
|
||||
struct mount_entry *dummy_mount_list;
|
||||
struct mount_entry *me;
|
||||
struct mount_entry **mtail = &dummy_mount_list;
|
||||
int cflags = REG_NOSUB | REG_EXTENDED;
|
||||
int found = 0, count = 0;
|
||||
|
||||
plan_tests(33);
|
||||
|
||||
ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
|
||||
np_add_name(&exclude_filesystem, "/var/log");
|
||||
ok(np_find_name(exclude_filesystem, "/var/log") == true, "is in list now");
|
||||
|
|
@ -47,6 +35,7 @@ int main(int argc, char **argv) {
|
|||
ok(np_find_name(exclude_filesystem, "/home") == true, "is in list now");
|
||||
ok(np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list");
|
||||
|
||||
struct name_list *exclude_fstype = NULL;
|
||||
ok(np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list");
|
||||
np_add_name(&exclude_fstype, "iso9660");
|
||||
ok(np_find_name(exclude_fstype, "iso9660") == true, "is in list now");
|
||||
|
|
@ -59,7 +48,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
*/
|
||||
|
||||
me = (struct mount_entry *)malloc(sizeof *me);
|
||||
struct mount_entry *dummy_mount_list;
|
||||
struct mount_entry **mtail = &dummy_mount_list;
|
||||
struct mount_entry *me = (struct mount_entry *)malloc(sizeof *me);
|
||||
me->me_devname = strdup("/dev/c0t0d0s0");
|
||||
me->me_mountdir = strdup("/");
|
||||
*mtail = me;
|
||||
|
|
@ -77,6 +68,7 @@ int main(int argc, char **argv) {
|
|||
*mtail = me;
|
||||
mtail = &me->me_next;
|
||||
|
||||
int cflags = REG_NOSUB | REG_EXTENDED;
|
||||
np_test_mount_entry_regex(dummy_mount_list, strdup("/"), cflags, 3, strdup("a"));
|
||||
np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), cflags, 3, strdup("regex on dev names:"));
|
||||
np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), cflags, 0, strdup("regex on non existent dev/path:"));
|
||||
|
|
@ -89,14 +81,16 @@ int main(int argc, char **argv) {
|
|||
np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
|
||||
np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
|
||||
|
||||
np_add_parameter(&paths, "/home/groups");
|
||||
np_add_parameter(&paths, "/var");
|
||||
np_add_parameter(&paths, "/tmp");
|
||||
np_add_parameter(&paths, "/home/tonvoon");
|
||||
np_add_parameter(&paths, "/dev/c2t0d0s0");
|
||||
filesystem_list test_paths = filesystem_list_init();
|
||||
mp_int_fs_list_append(&test_paths, "/home/groups");
|
||||
mp_int_fs_list_append(&test_paths, "/var");
|
||||
mp_int_fs_list_append(&test_paths, "/tmp");
|
||||
mp_int_fs_list_append(&test_paths, "/home/tonvoon");
|
||||
mp_int_fs_list_append(&test_paths, "/dev/c2t0d0s0");
|
||||
ok(test_paths.length == 5, "List counter works correctly with appends");
|
||||
|
||||
np_set_best_match(paths, dummy_mount_list, false);
|
||||
for (p = paths; p; p = p->name_next) {
|
||||
mp_int_fs_list_set_best_match(test_paths, dummy_mount_list, false);
|
||||
for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
|
||||
struct mount_entry *temp_me;
|
||||
temp_me = p->best_match;
|
||||
if (!strcmp(p->name, "/home/groups")) {
|
||||
|
|
@ -112,15 +106,19 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
paths = NULL; /* Bad boy - should free, but this is a test suite */
|
||||
np_add_parameter(&paths, "/home/groups");
|
||||
np_add_parameter(&paths, "/var");
|
||||
np_add_parameter(&paths, "/tmp");
|
||||
np_add_parameter(&paths, "/home/tonvoon");
|
||||
np_add_parameter(&paths, "/home");
|
||||
for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
|
||||
mp_int_fs_list_del(&test_paths, p);
|
||||
}
|
||||
ok(test_paths.length == 0, "List delete sets counter properly");
|
||||
|
||||
np_set_best_match(paths, dummy_mount_list, true);
|
||||
for (p = paths; p; p = p->name_next) {
|
||||
mp_int_fs_list_append(&test_paths, "/home/groups");
|
||||
mp_int_fs_list_append(&test_paths, "/var");
|
||||
mp_int_fs_list_append(&test_paths, "/tmp");
|
||||
mp_int_fs_list_append(&test_paths, "/home/tonvoon");
|
||||
mp_int_fs_list_append(&test_paths, "/home");
|
||||
|
||||
mp_int_fs_list_set_best_match(test_paths, dummy_mount_list, true);
|
||||
for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
|
||||
if (!strcmp(p->name, "/home/groups")) {
|
||||
ok(!p->best_match, "/home/groups correctly not found");
|
||||
} else if (!strcmp(p->name, "/var")) {
|
||||
|
|
@ -134,59 +132,66 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
/* test deleting first element in paths */
|
||||
paths = np_del_parameter(paths, NULL);
|
||||
for (p = paths; p; p = p->name_next) {
|
||||
if (!strcmp(p->name, "/home/groups"))
|
||||
found = 1;
|
||||
}
|
||||
ok(found == 0, "first element successfully deleted");
|
||||
found = 0;
|
||||
|
||||
p = paths;
|
||||
while (p) {
|
||||
if (!strcmp(p->name, "/tmp"))
|
||||
p = np_del_parameter(p, prev);
|
||||
else {
|
||||
prev = p;
|
||||
p = p->name_next;
|
||||
mp_int_fs_list_del(&test_paths, NULL);
|
||||
for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
|
||||
if (!strcmp(p->name, "/home/groups")) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
ok(!found, "first element successfully deleted");
|
||||
found = false;
|
||||
|
||||
for (p = paths; p; p = p->name_next) {
|
||||
if (!strcmp(p->name, "/tmp"))
|
||||
found = 1;
|
||||
if (p->name_next)
|
||||
prev = p;
|
||||
else
|
||||
last = p;
|
||||
parameter_list_elem *prev = NULL;
|
||||
parameter_list_elem *p = NULL;
|
||||
for (parameter_list_elem *path = test_paths.first; path; path = mp_int_fs_list_get_next(path)) {
|
||||
if (!strcmp(path->name, "/tmp")) {
|
||||
mp_int_fs_list_del(&test_paths, path);
|
||||
}
|
||||
p = path;
|
||||
}
|
||||
ok(found == 0, "/tmp element successfully deleted");
|
||||
|
||||
p = np_del_parameter(last, prev);
|
||||
for (p = paths; p; p = p->name_next) {
|
||||
if (!strcmp(p->name, "/home"))
|
||||
found = 1;
|
||||
parameter_list_elem *last = NULL;
|
||||
for (parameter_list_elem *path = test_paths.first; path; path = mp_int_fs_list_get_next(path)) {
|
||||
if (!strcmp(path->name, "/tmp")) {
|
||||
found = true;
|
||||
}
|
||||
if (path->next) {
|
||||
prev = path;
|
||||
} else {
|
||||
last = path;
|
||||
}
|
||||
}
|
||||
ok(!found, "/tmp element successfully deleted");
|
||||
|
||||
int count = 0;
|
||||
mp_int_fs_list_del(&test_paths, p);
|
||||
for (p = test_paths.first; p; p = p->next) {
|
||||
if (!strcmp(p->name, "/home")) {
|
||||
found = true;
|
||||
}
|
||||
last = p;
|
||||
count++;
|
||||
}
|
||||
ok(found == 0, "last (/home) element successfully deleted");
|
||||
ok(!found, "last (/home) element successfully deleted");
|
||||
ok(count == 2, "two elements remaining");
|
||||
|
||||
return exit_status();
|
||||
}
|
||||
|
||||
void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc) {
|
||||
int matches = 0;
|
||||
regex_t re;
|
||||
struct mount_entry *me;
|
||||
if (regcomp(&re, regstr, cflags) == 0) {
|
||||
for (me = dummy_mount_list; me; me = me->me_next) {
|
||||
if (np_regex_match_mount_entry(me, &re))
|
||||
regex_t regex;
|
||||
if (regcomp(®ex, regstr, cflags) == 0) {
|
||||
int matches = 0;
|
||||
for (struct mount_entry *me = dummy_mount_list; me; me = me->me_next) {
|
||||
if (np_regex_match_mount_entry(me, ®ex)) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
ok(matches == expect, "%s '%s' matched %i/3 entries. ok: %i/3", desc, regstr, expect, matches);
|
||||
|
||||
} else
|
||||
} else {
|
||||
ok(false, "regex '%s' not compilable", regstr);
|
||||
}
|
||||
}
|
||||
6
plugins/tests/test_check_disk.t
Executable file
6
plugins/tests/test_check_disk.t
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/perl
|
||||
use Test::More;
|
||||
if (! -e "./test_check_disk") {
|
||||
plan skip_all => "./test_check_disk not compiled - please enable libtap library to test";
|
||||
}
|
||||
exec "./test_check_disk";
|
||||
|
|
@ -76,7 +76,7 @@ char *strnl(char *);
|
|||
char *strpcpy(char *, const char *, const char *);
|
||||
char *strpcat(char *, const char *, const char *);
|
||||
int xvasprintf(char **strp, const char *fmt, va_list ap);
|
||||
int xasprintf(char **strp, const char *fmt, ...);
|
||||
int xasprintf(char **strp, const char *fmt, ...)__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
void usage(const char *) __attribute__((noreturn));
|
||||
void usage2(const char *, const char *) __attribute__((noreturn));
|
||||
|
|
|
|||
Loading…
Reference in a new issue