diff --git a/src/zabbix-agent/GNUmakefile b/src/zabbix-agent/GNUmakefile index d5c65df..2741afd 100644 --- a/src/zabbix-agent/GNUmakefile +++ b/src/zabbix-agent/GNUmakefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2015 Red Hat. +# Copyright (C) 2015-2016 Red Hat. # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published @@ -16,11 +16,16 @@ TOPDIR = ../.. include $(TOPDIR)/src/include/builddefs +SCRIPTS = zabbix-version SUBDIRS = src -default install: $(SUBDIRS) +default: $(SUBDIRS) $(SUBDIRS_MAKERULE) +install: $(SUBDIRS) $(SCRIPTS).sh + $(SUBDIRS_MAKERULE) + $(INSTALL) -m 644 $(SCRIPTS) $(PCP_BINADM_DIR)/$(SCRIPTS).sh + include $(BUILDRULES) default_pcp: default diff --git a/src/zabbix-agent/src/module.h b/src/zabbix-agent/src/module.h index aaccc61..91c32d1 100644 --- a/src/zabbix-agent/src/module.h +++ b/src/zabbix-agent/src/module.h @@ -1,5 +1,5 @@ /* -** Copyright (C) 2001-2015 Zabbix SIA +** Copyright (C) 2001-2016 Zabbix SIA ** ** 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 @@ -22,6 +22,8 @@ typedef __uint64_t zbx_uint64_t; #define ZBX_MODULE_API_VERSION_ONE 1 +#define get_rkey(request) (request)->key +#define get_rparams_num(request) (request)->nparam #define get_rparam(request, num) ((request)->nparam > num ? (request)->params[num] : NULL) /* flags for command */ @@ -49,17 +51,17 @@ typedef struct } AGENT_REQUEST; -typedef struct -{ - char *value; - char *source; - zbx_uint64_t lastlogsize; - int timestamp; - int severity; - int logeventid; - int mtime; -} -zbx_log_t; +struct zbx_log; +typedef struct zbx_log zbx_log_t; + +/* agent result types */ +#define AR_UINT64 0x01 +#define AR_DOUBLE 0x02 +#define AR_STRING 0x04 +#define AR_TEXT 0x08 +#define AR_LOG 0x10 +#define AR_MESSAGE 0x20 +#define AR_META 0x40 /* agent return structure */ typedef struct @@ -74,15 +76,21 @@ typedef struct /* null-terminated list of pointers */ zbx_log_t **logs; } -AGENT_RESULT; +AGENT_RESULT_V2; -/* agent result types */ -#define AR_UINT64 0x01 -#define AR_DOUBLE 0x02 -#define AR_STRING 0x04 -#define AR_TEXT 0x08 -#define AR_LOG 0x10 -#define AR_MESSAGE 0x20 +typedef struct +{ + zbx_uint64_t lastlogsize; /* meta information */ + zbx_uint64_t ui64; + double dbl; + char *str; + char *text; + char *msg; /* possible error message */ + zbx_log_t *log; + int type; /* flags: see AR_* above */ + int mtime; /* meta information */ +} +AGENT_RESULT_V3; /* SET RESULT */ @@ -113,13 +121,6 @@ AGENT_RESULT; ) /* NOTE: always allocate new memory for val! DON'T USE STATIC OR STACK MEMORY!!! */ -#define SET_LOG_RESULT(res, val) \ -( \ - (res)->type |= AR_LOG, \ - (res)->logs = (zbx_log_t **)(val) \ -) - -/* NOTE: always allocate new memory for val! DON'T USE STATIC OR STACK MEMORY!!! */ #define SET_MSG_RESULT(res, val) \ ( \ (res)->type |= AR_MESSAGE, \ diff --git a/src/zabbix-agent/src/zbxpcp.c b/src/zabbix-agent/src/zbxpcp.c index 5e20d4f..d9b2cc4 100644 --- a/src/zabbix-agent/src/zbxpcp.c +++ b/src/zabbix-agent/src/zbxpcp.c @@ -46,12 +46,14 @@ /* Zabbix includes. */ #include "module.h" +static int zbx_version; + /* * PCP connection */ static int ctx = -1; -int zbx_module_pcp_connect() +static int zbx_module_pcp_connect() { /* Load possible derived metric definitions. */ if (access(ZBX_PCP_DERIVED_CONFIG, F_OK ) != -1) @@ -61,16 +63,33 @@ int zbx_module_pcp_connect() return ctx; } -int zbx_module_pcp_disconnect() +static int zbx_module_pcp_disconnect() { return pmDestroyContext(ctx); } +static int zbx_get_version() +{ + char command[MAXPATHLEN]; + char *bindir; + int version; + + bindir = pmGetOptionalConfig("PCP_BINADM_DIR"); + if (!bindir) + return 2; + snprintf(command, sizeof(command), "%s/zabbix-version", bindir); + version = system(command); + if (version < 2) + version = 2; + return version; +} + /* * Zabbix connection */ int zbx_module_init() { + zbx_version = zbx_get_version(); if (zbx_module_pcp_connect() < 0) return ZBX_MODULE_FAIL; return ZBX_MODULE_OK; @@ -83,7 +102,7 @@ int zbx_module_api_version() static int metric_count = 0; static ZBX_METRIC *metrics = NULL; -void zbx_module_pcp_add_metric(const char *name); +static void zbx_module_pcp_add_metric(const char *name); ZBX_METRIC *zbx_module_item_list() { @@ -119,9 +138,10 @@ int zbx_module_uninit() /* * Zabbix/PCP connection */ -int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result); +static int zbx_module2_pcp_fetch_metric(AGENT_REQUEST *, AGENT_RESULT_V2 *); +static int zbx_module3_pcp_fetch_metric(AGENT_REQUEST *, AGENT_RESULT_V3 *); -void zbx_module_pcp_add_metric(const char *name) +static void zbx_module_pcp_add_metric(const char *name) { int sts; pmID pmid[1]; @@ -162,12 +182,15 @@ void zbx_module_pcp_add_metric(const char *name) if (metrics == NULL) { metrics = mptr; free(metric); free(param); return; } metrics[metric_count].key = metric; metrics[metric_count].flags = flags; - metrics[metric_count].function = zbx_module_pcp_fetch_metric; + if (zbx_version >= 3) + metrics[metric_count].function = zbx_module3_pcp_fetch_metric; + else + metrics[metric_count].function = zbx_module2_pcp_fetch_metric; metrics[metric_count].test_param = param; metric_count++; } -int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) +static int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, int *type, pmAtomValue *atom, char **errmsg) { int sts; char *metric[] = { request->key + strlen(ZBX_PCP_METRIC_PREFIX) }; @@ -175,7 +198,6 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) pmID pmid[1]; pmDesc desc[1]; pmResult *rp; - pmAtomValue atom; int iid = 0; int i; @@ -188,9 +210,8 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) inst = get_rparam(request, 0); break; default: - SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); + *errmsg = "Extraneous instance specification."; return SYSINFO_RET_FAIL; - break; } /* Try to reconnect if the initial lookup fails. */ @@ -198,7 +219,7 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) if (sts < 0 && (sts == PM_ERR_IPC || sts == -ECONNRESET)) { ctx = pmReconnectContext(ctx); if (ctx < 0) { - SET_MSG_RESULT(result, strdup("Not connected to pmcd.")); + *errmsg = "Not connected to pmcd."; return SYSINFO_RET_FAIL; } sts = pmLookupName(1, metric, pmid); @@ -209,18 +230,18 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) sts = pmLookupDesc(pmid[0], desc); if (sts < 0) return SYSINFO_RET_FAIL; if (inst != NULL && desc[0].indom == PM_INDOM_NULL) { - SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); + *errmsg = "Extraneous instance specification."; return SYSINFO_RET_FAIL; } if ((inst == NULL && desc[0].indom != PM_INDOM_NULL) || (request->nparam == 1 && !strlen(inst))) { - SET_MSG_RESULT(result, strdup("Missing instance specification.")); + *errmsg = "Missing instance specification."; return SYSINFO_RET_FAIL; } if (desc[0].indom != PM_INDOM_NULL) { iid = pmLookupInDom(desc[0].indom, inst); if (iid < 0) { - SET_MSG_RESULT(result, strdup("Instance not available.")); + *errmsg = "Instance not available."; return SYSINFO_RET_FAIL; } } @@ -230,7 +251,7 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) if (sts < 0) return SYSINFO_RET_FAIL; if (rp->vset[0]->numval < 1) { pmFreeResult(rp); - SET_MSG_RESULT(result, strdup("No value available.")); + *errmsg = "No value available."; return SYSINFO_RET_FAIL; } @@ -245,12 +266,30 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) /* Extract the wanted value. */ sts = pmExtractValue(rp->vset[0]->valfmt, &rp->vset[0]->vlist[i], - desc[0].type, &atom, desc[0].type); + desc[0].type, atom, desc[0].type); pmFreeResult(rp); if (sts < 0) return SYSINFO_RET_FAIL; + *type = desc[0].type; - /* Hand it to the caller. */ - switch(desc[0].type) { + /* Success. */ + return SYSINFO_RET_OK; +} + +static int zbx_module3_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT_V3 *result) +{ + char *errmsg = NULL; + pmAtomValue atom; + int type; + int sts; + + /* note: SET_*_RESULT macros evaluate to different code for v2/v3 */ + sts = zbx_module_pcp_fetch_metric(request, &type, &atom, &errmsg); + if (sts < 0) { + if (errmsg) + SET_MSG_RESULT(result, strdup(errmsg)); + return sts; + } + switch (type) { case PM_TYPE_32: SET_UI64_RESULT(result, atom.l); break; @@ -274,10 +313,53 @@ int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) break; default: SET_MSG_RESULT(result, strdup("Unsupported metric value type.")); - return SYSINFO_RET_FAIL; + sts = SYSINFO_RET_FAIL; break; } - /* Success. */ - return SYSINFO_RET_OK; + return sts; +} + +static int zbx_module2_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT_V2 *result) +{ + char *errmsg = NULL; + pmAtomValue atom; + int type; + int sts; + + /* note: SET_*_RESULT macros evaluate to different code for v2/v3 */ + sts = zbx_module_pcp_fetch_metric(request, &type, &atom, &errmsg); + if (sts < 0) { + if (errmsg) + SET_MSG_RESULT(result, strdup(errmsg)); + return sts; + } + switch (type) { + case PM_TYPE_32: + SET_UI64_RESULT(result, atom.l); + break; + case PM_TYPE_U32: + SET_UI64_RESULT(result, atom.ul); + break; + case PM_TYPE_64: + SET_UI64_RESULT(result, atom.ll); + break; + case PM_TYPE_U64: + SET_UI64_RESULT(result, atom.ull); + break; + case PM_TYPE_FLOAT: + SET_DBL_RESULT(result, atom.f); + break; + case PM_TYPE_DOUBLE: + SET_DBL_RESULT(result, atom.d); + break; + case PM_TYPE_STRING: + SET_STR_RESULT(result, strdup(atom.cp)); + break; + default: + SET_MSG_RESULT(result, strdup("Unsupported metric value type.")); + sts = SYSINFO_RET_FAIL; + break; + } + return sts; } diff --git a/src/zabbix-agent/zabbix-version.sh b/src/zabbix-agent/zabbix-version.sh new file mode 100755 index 0000000..2f5cda6 --- /dev/null +++ b/src/zabbix-agent/zabbix-version.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Copyright (c) 2016 Red Hat. +# +# 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 2 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. +# + +# Find Zabbix version from either zabbix_agentd or the environment - +# return it via exit code. + +version=2 # default +verbose=false +[ "X$1" = "X-v" ] && verbose=true + +get_version() +{ + # get X.Y.Z from final field of first row, extract major number + awk '{ $0=$NF; print; exit }' | awk -F. '{ printf("version=%d", $1) }' +} + +if [ -n "$ZABBIX_VERSION" ] +then + eval `echo "$ZABBIX_VERSION" | get_version` + $verbose && echo "Using version=$version from ZABBIX_VERSION" + exit $version +fi + +command=`which zabbix_agentd 2>/dev/null` +if [ $? -ne 0 ] +then + $verbose && echo "No zabbix_agentd found, using version=$version" + exit $version +fi + +eval `zabbix_agentd -V 2>/dev/null | get_version` +$verbose && echo "Using version=$version from $command -V" +exit $version