/* * Copyright 2010-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include "crm/crm.h" #include #include "crm/common/mainloop.h" #include "crm/services.h" #include "services_private.h" #include "services_nagios.h" /*! * \internal * \brief Prepare a Nagios action * * \param[in,out] op Action to prepare * * \return Standard Pacemaker return code */ int services__nagios_prepare(svc_action_t *op) { op->opaque->exec = pcmk__full_path(op->agent, NAGIOS_PLUGIN_DIR); op->opaque->args[0] = strdup(op->opaque->exec); if (op->opaque->args[0] == NULL) { return ENOMEM; } if (pcmk__str_eq(op->action, PCMK_ACTION_MONITOR, pcmk__str_casei) && (op->interval_ms == 0)) { // Invoke --version for a nagios probe op->opaque->args[1] = strdup("--version"); if (op->opaque->args[1] == NULL) { return ENOMEM; } } else if (op->params != NULL) { GHashTableIter iter; char *key = NULL; char *value = NULL; int index = 1; // 0 is already set to executable name g_hash_table_iter_init(&iter, op->params); while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { if (index > (PCMK__NELEM(op->opaque->args) - 2)) { return E2BIG; } if (pcmk__str_eq(key, PCMK_XA_CRM_FEATURE_SET, pcmk__str_casei) || strstr(key, CRM_META "_")) { continue; } op->opaque->args[index++] = crm_strdup_printf("--%s", key); op->opaque->args[index++] = strdup(value); if (op->opaque->args[index - 1] == NULL) { return ENOMEM; } } } // Nagios actions don't need to keep the parameters if (op->params != NULL) { g_hash_table_destroy(op->params); op->params = NULL; } return pcmk_rc_ok; } /*! * \internal * \brief Map a Nagios result to a standard OCF result * * \param[in] exit_status Nagios exit status * * \return Standard OCF result */ enum ocf_exitcode services__nagios2ocf(int exit_status) { switch (exit_status) { case NAGIOS_STATE_OK: return PCMK_OCF_OK; case NAGIOS_INSUFFICIENT_PRIV: return PCMK_OCF_INSUFFICIENT_PRIV; case NAGIOS_STATE_WARNING: return PCMK_OCF_DEGRADED; case NAGIOS_STATE_CRITICAL: case NAGIOS_STATE_UNKNOWN: default: return PCMK_OCF_UNKNOWN_ERROR; } } static inline char * nagios_metadata_name(const char *plugin) { return crm_strdup_printf(NAGIOS_METADATA_DIR "/%s.xml", plugin); } GList * services__list_nagios_agents(void) { GList *plugin_list = NULL; GList *result = NULL; plugin_list = services_os_get_directory_list(NAGIOS_PLUGIN_DIR, TRUE, TRUE); // Return only the plugins that have metadata for (GList *gIter = plugin_list; gIter != NULL; gIter = gIter->next) { struct stat st; const char *plugin = gIter->data; char *metadata = nagios_metadata_name(plugin); if (stat(metadata, &st) == 0) { result = g_list_append(result, strdup(plugin)); } free(metadata); } g_list_free_full(plugin_list, free); return result; } gboolean services__nagios_agent_exists(const char *name) { char *buf = NULL; gboolean rc = FALSE; struct stat st; if (name == NULL) { return rc; } buf = crm_strdup_printf(NAGIOS_PLUGIN_DIR "/%s", name); if (stat(buf, &st) == 0) { rc = TRUE; } free(buf); return rc; } int services__get_nagios_metadata(const char *type, char **output) { int rc = pcmk_ok; FILE *file_strm = NULL; int start = 0, length = 0, read_len = 0; char *metadata_file = nagios_metadata_name(type); file_strm = fopen(metadata_file, "r"); if (file_strm == NULL) { crm_err("Metadata file %s does not exist", metadata_file); free(metadata_file); return -EIO; } /* see how big the file is */ start = ftell(file_strm); fseek(file_strm, 0L, SEEK_END); length = ftell(file_strm); fseek(file_strm, 0L, start); CRM_ASSERT(length >= 0); CRM_ASSERT(start == ftell(file_strm)); if (length <= 0) { crm_info("%s was not valid", metadata_file); free(*output); *output = NULL; rc = -EIO; } else { crm_trace("Reading %d bytes from file", length); *output = pcmk__assert_alloc(1, (length + 1)); read_len = fread(*output, 1, length, file_strm); if (read_len != length) { crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len); free(*output); *output = NULL; rc = -EIO; } } fclose(file_strm); free(metadata_file); return rc; }