diff --git a/Makefile b/Makefile index cb58b15..9fc2db0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ WITH_RRD?=yes PLUGINS := ctstat diskstat hwmon load memory mount netdev random rtstat stat uptime vmstat -#PLUGINS += apache mysql conntrack alixusv ts2 diskstandby +#PLUGINS += apache mysql conntrack alixusv ts2 diskstandby hddptemp DESTDIR = BINARY_DIR = /usr/local/bin diff --git a/plugins/hddtemp.c b/plugins/hddtemp.c new file mode 100644 index 0000000..ebd08fc --- /dev/null +++ b/plugins/hddtemp.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * Copyright (C) 12/2012 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * 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. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include +#include +#include + +#include "configfile.h" +#include "helper.h" +#include "list.h" +#include "logging.h" +#include "plugins.h" +#include "probe.h" +#include "sockaddr.h" + +#define RESP_SIZE 1024 + +struct sammler_plugin plugin; + +struct server_entry { + struct list_head list; + + char *name; + int errors; + struct sockaddr_in sa; +}; + +static LIST_HEAD(server_list); +static char *resp_buf; + +static const char *ds_def = { + "DS:temperature:GAUGE:90:0:100" +}; + +static const char * get_ds(int ds_id) +{ + return ds_def; +} + +static int probe(void) +{ + struct server_entry *entry; + list_for_each_entry(entry, &server_list, list) { + + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + log_print(LOG_WARN, "%s: socket()", plugin.name); + continue; + } + + int ret = connect(sock, (struct sockaddr *)&entry->sa, sizeof(entry->sa)); + if (ret != 0) { + if (entry->errors++ == 0) + log_print(LOG_ERROR, "%s: connect(%s)", plugin.name, get_sockaddr_buf(&entry->sa)); + + close(sock); + continue; + } + + int pos = 0; + int len; + do { + len = read(sock, resp_buf + pos, RESP_SIZE - pos); + if ((pos == 0) && (len <= 0)) { + if (entry->errors++ == 0) + log_print(LOG_ERROR, "%s: read()", plugin.name); + + break; + } + + pos += len; + } while (len > 0); + + close(sock); + + if (pos == 0) + continue; + + resp_buf[pos] = '\0'; + + /* '|/dev/sda|OCZ-VERTEX3|128|C||/dev/sdb|HDT722525DLA380|SLP|*||/dev/sdc|Generic STORAGE DEVICE|NA|*|' */ + + char *tok, *tmp, *resp = resp_buf; + int i = 0; + char *device = NULL; + int temperature = 0; + while ((tok = strtok_r(resp, "|", &tmp)) != NULL) { + if ((i % 4) == 0) { + device = strrchr(tok, '/'); + if (device != NULL && *(device +1) == '\0') + device = NULL; + else + device++; + + } else if ((i % 4) == 2) { + char *tmp; + + temperature = strtol(tok, &tmp, 10); + if (*tmp != '\0') + device = NULL; + + } else if ((i % 4) == 3) { + if ((tok[0] == 'C') && (device != NULL)) { + char filename[32]; + len = snprintf(filename, sizeof(filename), "%s-%s.rrd", plugin.name, device); + if (len < 0 || len >= sizeof(filename)) + continue; + + probe_submit(&plugin, filename, 0, "%d", temperature); + } + + device = NULL; + temperature = 0; + } + i++; + + resp = NULL; + } + + if (entry->errors > 0) { + log_print(LOG_ERROR, "%s: success (%s) after %d errors", + plugin.name, entry->name, entry->errors); + + entry->errors = 0; + } + } + + return 0; +} + +static int init_cb(struct strtoken *tokens, void *privdata) +{ + if (tokens->count != 2) { + log_print(LOG_ERROR, "%s: parse error", plugin.name); + return -1; + } + + struct server_entry *entry = malloc(sizeof(struct server_entry)); + if (entry == NULL) { + log_print(LOG_ERROR, "%s: out of memory", plugin.name); + return -1; + } + + entry->name = strdup(tokens->field[0]); + entry->errors = 0; + + if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) { + log_print(LOG_ERROR, "%s: invalid address: <%s>", plugin.name, tokens->field[1]); + free(entry->name); + free(entry); + return -1; + } + + log_print(LOG_INFO, "%s: added server '%s'", plugin.name, entry->name); + list_add_tail(&entry->list, &server_list); + return 0; +} + +static int init(void) +{ + resp_buf = malloc(RESP_SIZE); + if (resp_buf == NULL) { + log_print(LOG_ERROR, "%s: out of memory", plugin.name); + return -1; + } + + int retval = config_get_strtokens("p_hddtemp", "server", ",", 2, init_cb, NULL); + + return (retval <= 0) ? -1 : 0; +} + +static int fini(void) +{ + struct server_entry *entry, *tmp; + list_for_each_entry_safe(entry, tmp, &server_list, list) { + free(entry->name); + free(entry); + } + + free(resp_buf); + return 0; +} + +struct sammler_plugin plugin = { + .name = "hddtemp", + .interval = 60, + .init = &init, + .fini = &fini, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/sammler.conf b/sammler.conf index 89f7808..9fbaffc 100644 --- a/sammler.conf +++ b/sammler.conf @@ -29,6 +29,7 @@ plugin random.so #plugin alixusv.so #plugin ts2.so #plugin diskstandby.so +#plugin hddtemp.so # 1h(10s), 12h(1min), 48h(2min), 14d(15min), 4w(60min), 2y(12h) rra RRA:MIN:0.5:1:360 RRA:AVERAGE:0.5:1:360 RRA:MAX:0.5:1:360 @@ -56,3 +57,6 @@ rra RRA:MIN:0.5:4320:1440 RRA:AVERAGE:0.5:4320:1440 RRA:MAX:0.5:4320:1440 [p_diskstandby] #device /dev/sda + +[p_hddtemp] +server test,127.0.0.1:7634