diff options
author | Constantine A. Murenin <cnst@cvs.openbsd.org> | 2007-05-30 07:49:38 +0000 |
---|---|---|
committer | Constantine A. Murenin <cnst@cvs.openbsd.org> | 2007-05-30 07:49:38 +0000 |
commit | 598c2422d97e24eead099347fe8d7d5295ae8eba (patch) | |
tree | 6515c92f023ec21544f2d5983b6aceb5c2cb84c4 | |
parent | fcdde353bb85f1845ab4e0db235f42e459898b86 (diff) |
Major update to sensorsd.
Improves support for both 'smart' (those providing sensor status) and
'old-style' sensors.
Due to re-design, the following improvements are now present and many
flaws are now gone:
== for smart sensors ==
* automatically monitor all sensors that provide status by themselves,
with the possibility to ignore certain individual sensors or sensors
of certain type (appropriate template for sensorsd.conf is included)
* report actual sensor status as provided by the driver. Previously,
WARN, CRITICAL and UNKNOWN statuses were considered the same, but
now they are different and will be reported separately. This also
improves readability of the log-files and consistency with sysctl
output.
* ability to ignore status provided by the driver with the 'istatus'
keyword ("ignore automatic status" or "I set the status"), with the
possibility to set your own settings for acceptable limits.
Previously, it was not possible to set any kind of user limits for
those sensors that had their own status facilities.
== for old-style sensors ==
* previously, lm(4)-style fans that were flagged SENSOR_FINVALID during
sensorsd startup were completely ignored, but now their invalid status
is appropriately reported, and they are monitored again when they come
out of their invalid mode
* previously, a sensor that had an empty entry in the configuration file
was reported to be "within limits", but now it will not be monitored
at all (unless, of cause, it provides its own status)
As a bonus, sensorsd syslog entries should now be shorter, and the
majority of them will fit on one line on 80-column terminals.
ok beck@, henning@, deraadt@
-rw-r--r-- | etc/sensorsd.conf | 29 | ||||
-rw-r--r-- | usr.sbin/sensorsd/sensorsd.8 | 6 | ||||
-rw-r--r-- | usr.sbin/sensorsd/sensorsd.c | 170 | ||||
-rw-r--r-- | usr.sbin/sensorsd/sensorsd.conf.5 | 34 |
4 files changed, 178 insertions, 61 deletions
diff --git a/etc/sensorsd.conf b/etc/sensorsd.conf index 2fe1f2551bd..e4eb6c36785 100644 --- a/etc/sensorsd.conf +++ b/etc/sensorsd.conf @@ -1,4 +1,4 @@ -# $OpenBSD: sensorsd.conf,v 1.6 2007/05/29 06:04:41 jmc Exp $ +# $OpenBSD: sensorsd.conf,v 1.7 2007/05/30 07:49:37 cnst Exp $ # # Sample sensorsd.conf file. See sensorsd.conf(5) for details. @@ -19,14 +19,31 @@ # CPU fan (RPM) #hw.sensors.lm0.fan1:low=3000 -# Warn if indicator status changes, -# e.g. intrusion detection on ipmi. -#indicator: +# ignore certain indicators on ipmi(4) +#hw.sensors.ipmi0.indicator1:istatus # Warn if any temperature sensor is over 70 degC. # This entry will match only those temperature sensors # that don't have their own entry and don't keep state. #temp:high=70C -# RAID drive status changes -#drive: + +# By default, sensorsd(8) reports status changes of all sensors that +# keep their state. Uncomment the following lines if you want to +# suppress reports about status changes of specific sensor types. + +#temp:istatus +#fan:istatus +#volt:istatus +#acvolt:istatus +#resistance:istatus +#power:istatus +#current:istatus +#watthour:istatus +#amphour:istatus +#indicator:istatus +#raw:istatus +#percentage:istatus +#illuminance:istatus +#drive:istatus +#timedelta:istatus diff --git a/usr.sbin/sensorsd/sensorsd.8 b/usr.sbin/sensorsd/sensorsd.8 index 1f943242d37..80b049ddfd5 100644 --- a/usr.sbin/sensorsd/sensorsd.8 +++ b/usr.sbin/sensorsd/sensorsd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sensorsd.8,v 1.9 2006/04/21 08:35:00 jmc Exp $ +.\" $OpenBSD: sensorsd.8,v 1.10 2007/05/30 07:49:37 cnst Exp $ .\" .\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org> .\" Copyright (c) 2005 Matthew Gream <matthew.gream@pobox.com> @@ -35,6 +35,10 @@ If the data is out of given limits, an alert is sent using .Xr syslog 3 and a command, if specified, is executed. .Pp +By default, +.Nm +also monitors status changes on all sensors that keep their state. +.Pp Limit and command values for a particular sensor may be specified in the .Xr sensorsd.conf 5 configuration file. diff --git a/usr.sbin/sensorsd/sensorsd.c b/usr.sbin/sensorsd/sensorsd.c index 01e17b4e670..e579cdd24b3 100644 --- a/usr.sbin/sensorsd/sensorsd.c +++ b/usr.sbin/sensorsd/sensorsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sensorsd.c,v 1.31 2007/05/29 20:30:40 cnst Exp $ */ +/* $OpenBSD: sensorsd.c,v 1.32 2007/05/30 07:49:37 cnst Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -46,6 +46,13 @@ void parse_config(char *); int64_t get_val(char *, int, enum sensor_type); void reparse_cfg(int); +enum sensorsd_s_status { + SENSORSD_S_UNSPEC, /* status is unspecified */ + SENSORSD_S_INVALID, /* status is invalid, per SENSOR_FINVALID */ + SENSORSD_S_WITHIN, /* status is within limits */ + SENSORSD_S_OUTSIDE /* status is outside limits */ +}; + struct limits_t { TAILQ_ENTRY(limits_t) entries; char dxname[16]; /* device unix name */ @@ -56,11 +63,17 @@ struct limits_t { int64_t lower; /* lower limit */ int64_t upper; /* upper limit */ char *command; /* failure command */ - time_t status_changed; - enum sensor_status status; /* last status */ - enum sensor_status status2; - int count; /* stat change counter */ - u_int8_t watch; + time_t astatus_changed; + time_t ustatus_changed; + enum sensor_status astatus; /* last automatic status */ + enum sensor_status astatus2; + enum sensorsd_s_status ustatus; /* last user-limit status */ + enum sensorsd_s_status ustatus2; + int acount; /* stat change counter */ + int ucount; /* stat change counter */ + u_int8_t flags; /* sensorsd limit flags */ +#define SENSORSD_L_USERLIMIT 0x0001 /* user specified limit */ +#define SENSORSD_L_ISTATUS 0x0002 /* ignore automatic status */ }; TAILQ_HEAD(limits, limits_t) limits = TAILQ_HEAD_INITIALIZER(limits); @@ -122,8 +135,6 @@ main(int argc, char *argv[]) warn("sysctl"); continue; } - if (sensor.flags & SENSOR_FINVALID) - continue; if ((limit = calloc(1, sizeof(struct limits_t))) == NULL) err(1, "calloc"); @@ -189,45 +200,62 @@ check_sensors(void) struct limits_t *limit; size_t len; int mib[5]; - enum sensor_status newstatus; mib[0] = CTL_HW; mib[1] = HW_SENSORS; len = sizeof(sensor); - TAILQ_FOREACH(limit, &limits, entries) - if (limit->watch) { - mib[2] = limit->dev; - mib[3] = limit->type; - mib[4] = limit->numt; - if (sysctl(mib, 5, &sensor, &len, NULL, 0) == -1) - err(1, "sysctl"); - - newstatus = sensor.status; - /* unknown may as well mean producing valid - * status had failed so warn about it */ - if (newstatus == SENSOR_S_UNKNOWN) - newstatus = SENSOR_S_WARN; - else if (newstatus == SENSOR_S_UNSPEC) { - if (sensor.value > limit->upper || - sensor.value < limit->lower) - newstatus = SENSOR_S_CRIT; - else - newstatus = SENSOR_S_OK; - } + TAILQ_FOREACH(limit, &limits, entries) { + if ((limit->flags & SENSORSD_L_ISTATUS) && + !(limit->flags & SENSORSD_L_USERLIMIT)) + continue; + + mib[2] = limit->dev; + mib[3] = limit->type; + mib[4] = limit->numt; + if (sysctl(mib, 5, &sensor, &len, NULL, 0) == -1) + err(1, "sysctl"); + + if (!(limit->flags & SENSORSD_L_ISTATUS)) { + enum sensor_status newastatus = sensor.status; - if (limit->status != newstatus) { - if (limit->status2 != newstatus) { - limit->status2 = newstatus; - limit->count = 0; - } else if (++limit->count >= 3) { + if (limit->astatus != newastatus) { + if (limit->astatus2 != newastatus) { + limit->astatus2 = newastatus; + limit->acount = 0; + } else if (++limit->acount >= 3) { + limit->last_val = sensor.value; + limit->astatus2 = + limit->astatus = newastatus; + limit->astatus_changed = time(NULL); + } + } + } + + if (limit->flags & SENSORSD_L_USERLIMIT) { + enum sensorsd_s_status newustatus; + + if (sensor.flags & SENSOR_FINVALID) + newustatus = SENSORSD_S_INVALID; + else if (sensor.value > limit->upper || + sensor.value < limit->lower) + newustatus = SENSORSD_S_OUTSIDE; + else + newustatus = SENSORSD_S_WITHIN; + + if (limit->ustatus != newustatus) { + if (limit->ustatus2 != newustatus) { + limit->ustatus2 = newustatus; + limit->ucount = 0; + } else if (++limit->ucount >= 3) { limit->last_val = sensor.value; - limit->status2 = - limit->status = newstatus; - limit->status_changed = time(NULL); + limit->ustatus2 = + limit->ustatus = newustatus; + limit->ustatus_changed = time(NULL); } } } + } } void @@ -254,13 +282,61 @@ report(time_t last_report) struct limits_t *limit = NULL; TAILQ_FOREACH(limit, &limits, entries) { - if (limit->status_changed <= last_report) + if ((limit->astatus_changed <= last_report) && + (limit->ustatus_changed <= last_report)) continue; - syslog(LOG_ALERT, "hw.sensors.%s.%s%d: %s limits, value: %s", - limit->dxname, sensor_type_s[limit->type], limit->numt, - (limit->status != SENSOR_S_OK) ? "exceed" : "within", - print_sensor(limit->type, limit->last_val)); + if (limit->astatus_changed > last_report) { + const char *as = NULL; + + switch (limit->astatus) { + case SENSOR_S_UNSPEC: + as = ""; + break; + case SENSOR_S_OK: + as = ", OK"; + break; + case SENSOR_S_WARN: + as = ", WARN"; + break; + case SENSOR_S_CRIT: + as = ", CRITICAL"; + break; + case SENSOR_S_UNKNOWN: + as = ", UNKNOWN"; + break; + } + syslog(LOG_ALERT, "%s.%s%d: %s%s", + limit->dxname, sensor_type_s[limit->type], + limit->numt, + print_sensor(limit->type, limit->last_val), as); + } + + if (limit->ustatus_changed > last_report) { + char us[BUFSIZ]; + + switch (limit->ustatus) { + case SENSORSD_S_UNSPEC: + snprintf(us, sizeof(us), + "ustatus uninitialised"); + break; + case SENSORSD_S_INVALID: + snprintf(us, sizeof(us), "marked invalid"); + break; + case SENSORSD_S_WITHIN: + snprintf(us, sizeof(us), "within limits: %s", + print_sensor(limit->type, limit->last_val)); + break; + case SENSORSD_S_OUTSIDE: + snprintf(us, sizeof(us), "exceeds limits: %s", + print_sensor(limit->type, limit->last_val)); + break; + } + syslog(LOG_ALERT, "%s.%s%d: %s", + limit->dxname, sensor_type_s[limit->type], + limit->numt, us); + } + if (limit->command) { int i = 0, n = 0, r; char *cmd = limit->command; @@ -402,12 +478,12 @@ parse_config(char *cf) next = TAILQ_NEXT(p, entries); snprintf(node, sizeof(node), "hw.sensors.%s.%s%d", p->dxname, sensor_type_s[p->type], p->numt); + p->flags = 0; if (cgetent(&buf, cfa, node) != 0) - if (cgetent(&buf, cfa, sensor_type_s[p->type]) != 0) { - p->watch = 0; + if (cgetent(&buf, cfa, sensor_type_s[p->type]) != 0) continue; - } - p->watch = 1; + if (cgetcap(buf, "istatus", ':')) + p->flags |= SENSORSD_L_ISTATUS; if (cgetstr(buf, "low", &ebuf) < 0) ebuf = NULL; p->lower = get_val(ebuf, 0, p->type); @@ -420,6 +496,8 @@ parse_config(char *cf) asprintf(&(p->command), "%s", ebuf); free(buf); buf = NULL; + if (p->lower != LLONG_MIN || p->upper != LLONG_MAX) + p->flags |= SENSORSD_L_USERLIMIT; } free(cfa); } diff --git a/usr.sbin/sensorsd/sensorsd.conf.5 b/usr.sbin/sensorsd/sensorsd.conf.5 index 45aab7ffc1c..cd78b5ecdfc 100644 --- a/usr.sbin/sensorsd/sensorsd.conf.5 +++ b/usr.sbin/sensorsd/sensorsd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sensorsd.conf.5,v 1.12 2007/05/29 06:04:41 jmc Exp $ +.\" $OpenBSD: sensorsd.conf.5,v 1.13 2007/05/30 07:49:37 cnst Exp $ .\" .\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org> .\" Copyright (c) 2005 Matthew Gream <matthew.gream@pobox.com> @@ -32,8 +32,9 @@ to configure hardware sensor monitoring. Each valid sensor registered in the system is matched by at most one entry in .Nm , -which may specify high and low limits. -If the limits are crossed, +which may specify high and low limits, +and whether sensor status changes provided by driver should be ignored. +If the limits are crossed or if status provided by the driver changes, .Xr sensorsd 8 's alert functionality is triggered and a command, if specified, is executed. @@ -51,7 +52,7 @@ sensor is not present in .Nm , then an entry .Va temp -will be looked at to determine the limits. +will be looked at to determine the settings. The following attributes may be used: .Pp .Bl -tag -width "commandXX" -offset indent -compact @@ -61,6 +62,8 @@ Specify a command to be executed if limits are crossed. Specify an upper limit. .It Li low Specify a lower limit. +.It Li istatus +Specify to ignore status provided by the driver. .El .Pp The values for temperature sensors can be given in degrees Celsius or @@ -92,6 +95,15 @@ the sensor's low limit .It %4 the sensor's high limit .El +.Pp +By default, +.Xr sensorsd 8 +monitors status changes on all sensors that keep their state. +This behaviour may be altered by using the +.Dq istatus +attribute, +for example, you may specify to ignore status changes of sensors with +certain type, or of any individual sensors. .Sh FILES .Bl -tag -width "/etc/sensorsd.conf" .It /etc/sensorsd.conf @@ -108,18 +120,24 @@ Alerts will be sent if hw.sensors.ipmi0.temp1 goes above 170F; if hw.sensors.lm0.volt3 goes below 4.8V or above 5.2V; if the speed of the fan attached to hw.sensors.lm0.fan1 goes below 1000RPM or above 8000RPM; -or if hw.sensors.ami0.drive0, -attached to raid volume sd0, +if any RAID volume drive goes into a state other than .Dq OK , -such as drive failure, rebuild, or a complete failure. +such as drive failure, rebuild, or a complete failure, the command +.Pa /etc/sensorsd/drive +will be executed, with the sensor number passed to it; however, +no alerts will be generated for status changes on timedelta sensors. +For all other sensors whose drivers automatically provide +sensor status updates, alerts will be generated +each time those sensors undergo status transitions. .Bd -literal -offset indent # Comments are allowed hw.sensors.ipmi0.temp0:high=80C:command=/etc/sensorsd/log_warning %t %n %2 hw.sensors.ipmi0.temp1:high=170F hw.sensors.lm0.volt3:low=4.8V:high=5.2V hw.sensors.lm0.fan1:low=1000:high=8000 -hw.sensors.ami0.drive0: # raid volume status changes +drive:command=/etc/sensorsd/drive %n +timedelta:istatus #ignore status changes for timedelta .Ed .Sh SEE ALSO .Xr getcap 3 , |