summaryrefslogtreecommitdiffstats
path: root/lib/services/services_nagios.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/services/services_nagios.c')
-rw-r--r--lib/services/services_nagios.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/lib/services/services_nagios.c b/lib/services/services_nagios.c
new file mode 100644
index 0000000..abddca8
--- /dev/null
+++ b/lib/services/services_nagios.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2010-2022 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 <crm_internal.h>
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <grp.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "crm/crm.h"
+#include <crm/msg_xml.h>
+#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, "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, XML_ATTR_CRM_VERSION, 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 = calloc(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;
+}