Merge pull request #1801 from KriSchu/feature_check_disk_add_ignore_missing_option

check_disk: add ignore-missing option to return OK for missing fs
This commit is contained in:
Lorenz 2023-03-11 10:27:43 +01:00 committed by GitHub
commit 357787868b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 135 additions and 24 deletions

View file

@ -47,9 +47,10 @@ 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 *) name;
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;
@ -75,13 +76,17 @@ np_add_parameter(struct parameter_list **list, const char *name)
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;
}
@ -90,6 +95,9 @@ np_add_parameter(struct parameter_list **list, const char *name)
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)
@ -97,10 +105,17 @@ np_del_parameter(struct parameter_list *item, struct parameter_list *prev)
else
next = NULL;
free(item);
if (next)
next->name_prev = prev;
if (prev)
prev->name_next = next;
if (item->name) {
free(item->name);
}
free(item);
return next;
}

View file

@ -24,6 +24,7 @@ struct parameter_list
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;

View file

@ -112,11 +112,12 @@ enum
{
SYNC_OPTION = CHAR_MAX + 1,
NO_SYNC_OPTION,
BLOCK_SIZE_OPTION
BLOCK_SIZE_OPTION,
IGNORE_MISSING
};
#ifdef _AIX
#pragma alloca
#pragma alloca
#endif
int process_arguments (int, char **);
@ -126,7 +127,7 @@ int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, ch
void print_help (void);
void print_usage (void);
double calculate_percent(uintmax_t, uintmax_t);
void stat_path (struct parameter_list *p);
bool stat_path (struct parameter_list *p);
void get_stats (struct parameter_list *p, struct fs_usage *fsp);
void get_path_stats (struct parameter_list *p, struct fs_usage *fsp);
@ -140,6 +141,7 @@ int verbose = 0;
int erronly = FALSE;
int display_mntp = FALSE;
int exact_match = FALSE;
bool ignore_missing = false;
int freespace_ignore_reserved = FALSE;
int display_inodes_perfdata = FALSE;
char *warn_freespace_units = NULL;
@ -155,6 +157,7 @@ char *crit_usedinodes_percent = NULL;
char *warn_freeinodes_percent = NULL;
char *crit_freeinodes_percent = NULL;
int path_selected = FALSE;
bool path_ignored = false;
char *group = NULL;
struct stat *stat_buf;
struct name_list *seen = NULL;
@ -166,10 +169,12 @@ main (int argc, char **argv)
int result = STATE_UNKNOWN;
int disk_result = STATE_UNKNOWN;
char *output;
char *ignored;
char *details;
char *perf;
char *perf_ilabel;
char *preamble;
char *preamble = " - free space:";
char *ignored_preamble = " - ignored paths:";
char *flag_header;
int temp_result;
@ -181,8 +186,8 @@ main (int argc, char **argv)
char mountdir[32];
#endif
preamble = strdup (" - free space:");
output = strdup ("");
ignored = strdup ("");
details = strdup ("");
perf = strdup ("");
perf_ilabel = strdup ("");
@ -203,7 +208,7 @@ main (int argc, char **argv)
/* If a list of paths has not been selected, find entire
mount list and create list of paths
*/
if (path_selected == FALSE) {
if (path_selected == FALSE && path_ignored == false) {
for (me = mount_list; me; me = me->me_next) {
if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) {
path = np_add_parameter(&path_select_list, me->me_mountdir);
@ -213,17 +218,40 @@ main (int argc, char **argv)
set_all_thresholds(path);
}
}
np_set_best_match(path_select_list, mount_list, exact_match);
if (path_ignored == false) {
np_set_best_match(path_select_list, mount_list, exact_match);
}
/* Error if no match found for specified paths */
temp_list = path_select_list;
while (temp_list) {
if (! temp_list->best_match) {
die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name);
while (path_select_list) {
if (! path_select_list->best_match && ignore_missing == true) {
/* If the first element will be deleted, the temp_list must be updated with the new start address as well */
if (path_select_list == temp_list) {
temp_list = path_select_list->name_next;
}
/* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
xasprintf (&ignored, "%s %s;", ignored, path_select_list->name);
/* Delete the path from the list so that it is not stat-checked later in the code. */
path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
} else if (! path_select_list->best_match) {
/* Without --ignore-missing option, exit with Critical state. */
die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
} else {
/* Continue jumping through the list */
path_select_list = path_select_list->name_next;
}
}
temp_list = temp_list->name_next;
path_select_list = temp_list;
if (! path_select_list && ignore_missing == true) {
result = STATE_OK;
if (verbose >= 2) {
printf ("None of the provided paths were found\n");
}
}
/* Process for every path in list */
@ -242,6 +270,10 @@ main (int argc, char **argv)
me = path->best_match;
if (!me) {
continue;
}
#ifdef __CYGWIN__
if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
continue;
@ -260,8 +292,12 @@ main (int argc, char **argv)
if (path->group == NULL) {
/* Skip remote filesystems if we're not interested in them */
if (me->me_remote && show_local_fs) {
if (stat_remote_fs)
stat_path(path);
if (stat_remote_fs) {
if (!stat_path(path) && ignore_missing == true) {
result = STATE_OK;
xasprintf (&ignored, "%s %s;", ignored, path->name);
}
}
continue;
/* Skip pseudo fs's if we haven't asked for all fs's */
} else if (me->me_dummy && !show_all_fs) {
@ -280,7 +316,13 @@ main (int argc, char **argv)
}
}
stat_path(path);
if (!stat_path(path)) {
if (ignore_missing == true) {
result = STATE_OK;
xasprintf (&ignored, "%s %s;", ignored, path->name);
}
continue;
}
get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
@ -411,8 +453,12 @@ main (int argc, char **argv)
if (verbose >= 2)
xasprintf (&output, "%s%s", output, details);
if (strcmp(output, "") == 0 && ! erronly) {
preamble = "";
xasprintf (&output, " - No disks were found for provided parameters;");
}
printf ("DISK %s%s%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf);
printf ("DISK %s%s%s%s%s|%s\n", state_text (result), ((erronly && result==STATE_OK)) ? "" : preamble, output, (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
return result;
}
@ -481,6 +527,7 @@ process_arguments (int argc, char **argv)
{"ignore-ereg-partition", required_argument, 0, 'i'},
{"ignore-eregi-path", required_argument, 0, 'I'},
{"ignore-eregi-partition", required_argument, 0, 'I'},
{"ignore-missing", no_argument, 0, IGNORE_MISSING},
{"local", no_argument, 0, 'l'},
{"stat-remote-fs", no_argument, 0, 'L'},
{"iperfdata", no_argument, 0, 'P'},
@ -632,12 +679,19 @@ process_arguments (int argc, char **argv)
/* add parameter if not found. overwrite thresholds if path has already been added */
if (! (se = np_find_parameter(path_select_list, optarg))) {
se = np_add_parameter(&path_select_list, optarg);
if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
path_ignored = true;
break;
}
}
se->group = group;
set_all_thresholds(se);
/* With autofs, it is required to stat() the path before re-populating the mount_list */
stat_path(se);
if (!stat_path(se)) {
break;
}
/* NB: We can't free the old mount_list "just like that": both list pointers and struct
* pointers are copied around. One of the reason it wasn't done yet is that other parts
* of check_disk need the same kind of cleanup so it'd better be done as a whole */
@ -718,6 +772,9 @@ process_arguments (int argc, char **argv)
cflags = default_cflags;
break;
case IGNORE_MISSING:
ignore_missing = true;
break;
case 'A':
optarg = strdup(".*");
// Intentional fallthrough
@ -753,7 +810,11 @@ process_arguments (int argc, char **argv)
}
}
if (!fnd)
if (!fnd && ignore_missing == true) {
path_ignored = true;
/* path_selected = TRUE;*/
break;
} else if (!fnd)
die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"),
_("Regular expression did not match any path or disk"), optarg);
@ -923,6 +984,9 @@ print_help (void)
printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
printf (" %s\n", "--ignore-missing");
printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
printf (" %s\n", "-u, --units=STRING");
printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
@ -956,7 +1020,7 @@ print_usage (void)
printf ("[-t timeout] [-u unit] [-v] [-X type] [-N type]\n");
}
void
bool
stat_path (struct parameter_list *p)
{
/* Stat entry to check that dir exists and is accessible */
@ -965,9 +1029,14 @@ stat_path (struct parameter_list *p)
if (stat (p->name, &stat_buf[0])) {
if (verbose >= 3)
printf("stat failed on %s\n", p->name);
printf("DISK %s - ", _("CRITICAL"));
die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
if (ignore_missing == true) {
return false;
} else {
printf("DISK %s - ", _("CRITICAL"));
die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
}
}
return true;
}
@ -987,7 +1056,8 @@ get_stats (struct parameter_list *p, struct fs_usage *fsp) {
continue;
#endif
if (p_list->group && ! (strcmp(p_list->group, p->group))) {
stat_path(p_list);
if (! stat_path(p_list))
continue;
get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
get_path_stats(p_list, &tmpfsp);
if (verbose >= 3)

View file

@ -23,7 +23,7 @@ my $mountpoint2_valid = getTestParameter( "NP_MOUNTPOINT2_VALID", "Path to anoth
if ($mountpoint_valid eq "" or $mountpoint2_valid eq "") {
plan skip_all => "Need 2 mountpoints to test";
} else {
plan tests => 78;
plan tests => 88;
}
$result = NPTest->testCmd(
@ -351,3 +351,28 @@ unlike( $result->output, qr/$mountpoint2_valid/, "output data does not have $mou
$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -i '^barbazJodsf\$'");
like( $result->output, qr/$mountpoint_valid/, "ignore: output data does have $mountpoint_valid when regex doesn't match");
like( $result->output, qr/$mountpoint2_valid/,"ignore: output data does have $mountpoint2_valid when regex doesn't match");
# 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');
# 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');
# 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');
# 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');