From: Florian Forster Date: Sat, 9 May 2009 10:29:44 +0000 (+0200) Subject: Merge branch 'collectd-4.5' into collectd-4.6 X-Git-Tag: collectd-4.7.0~13^2 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=37905c5a2370c8e6edae5011978773eeaa589d09;hp=39f3ecb1fc15fb1978c7ac6ccc1c6a9091785604 Merge branch 'collectd-4.5' into collectd-4.6 --- diff --git a/.gitignore b/.gitignore index 03bd0c46..1f491f31 100644 --- a/.gitignore +++ b/.gitignore @@ -31,11 +31,9 @@ config.log config.status libtool src/.deps -src/Makefile src/collectd.conf src/config.h -src/libconfig/Makefile -src/liboping/Makefile +src/libcollectdclient/libcollectdclient.pc src/stamp-h1 # make stuff: @@ -50,6 +48,10 @@ src/collectd*.1 src/collectd*.5 src/types.db.5 src/config.h.in~ +src/libcollectdclient/.libs +src/libcollectdclient/*.la +src/libcollectdclient/*.lo +src/libcollectdclient/lcc_features.h src/libiptc/.libs src/libiptc/*.la src/libiptc/*.lo diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..9bb4399e --- /dev/null +++ b/.mailmap @@ -0,0 +1,8 @@ +Anthony +Florian Forster +Florian Forster +LuboÅ¡ Staněk +LuboÅ¡ Staněk +Niki W. Waibel +Sebastian Harl + diff --git a/AUTHORS b/AUTHORS index 234d431e..782e8f2b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -27,6 +27,12 @@ Anthony Gialluca Antony Dovgal - memcached plugin. +Bruno Prémont + - BIND plugin. + - Many bugreports and -fixes in various plugins, + especially a nasty bug in the network plugin. + - Wireshark dissector. + Christophe Kalt - The version 3 `log' mode. - Many Solaris related hints and fixes. @@ -37,6 +43,15 @@ Dan Berrange David Bacher - serial plugin. +Doug MacEachern + - The `-T' option (config testing mode). + - OpenVPN plugin. + - jcollectd (two-way JMX integration). + - A few other patches to various plugins. + +Fabian Linzberger + - Percentage aggregation for `collectd-nagios'. + Flavio Stanchina - mbmon plugin. @@ -54,9 +69,16 @@ Luke Herberling Lyonel Vincent - processes plugin. -Michael Stapelberg +Michael Stapelberg - OpenBSD port of the tcpconns plugin. +Michał Mirosław + - thermal plugin. + - Streamlines recursive directory traversion. + +Mirko Buffoni + - Port/Socket selection in the MySQL plugin. + Niki W. Waibel - Initial autotools fixes. - libltdl code. @@ -75,10 +97,16 @@ Peter Holik - Some bugfixes in the exec plugin. - Notifications in the ipmi plugin. +Piotr Hosowicz + - SMF manifest for collectd. + Richard W. M. Jones - libvirt plugin. - uuid plugin. +Roman Klesel + - Oracle schema and sample SQL statements to be used with the Oracle plugin. + Scott Garrett - tape plugin. diff --git a/ChangeLog b/ChangeLog index 2c1f8d89..924d4045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,102 @@ +2009-03-18, Version 4.6.2 + * collectd: Some Solaris utility code has been improved. + * filter subsystem: Allow `Chains' without default targets. + * liboping: A patch to comply with strict aliasing rules has been + added. + * timediff match: Fix a typo: The match was registered with a wrong + name which prevented this match to be used as documented. Thanks to + Bruno Prémont for finding this problem. + * bind plugin: Fix collection of the cached RR sets. The number of RR + sets currently in the cache was collected as a counter value, which + is nonsense. Thanks to Bruno Prémont for implementing this. + * dns plugin: Don't pass NULL to `pcap_open_live': Some systems, + primarily BSDs, don't take it well and crash. + * oracle plugin: Portability to 64 bit systems has been improved. + * postgresql plugin: The default configuration has been improved. + * rrdtool plugin: Fix a possible race condition: If the network plugin + is brought and dispatches a value before the rrdtool plugin is + initialized, the daemon may crash. + +2009-02-22, Version 4.6.1 + * collectd: Many documentation fixes. + * Collectd::Unixsock: Error handling has been improved. + * regex match: Don't link with the PCRE library. + * bind plugin: Various bugs have been fixed. Thanks to Bruno Prémont + for finding and fixing most of them. + * ipmi plugin: Fix an off-by-one error which could cause segmentation + faults. Thanks to Peter Holik for his patch. + +2009-02-16, Version 4.6.0 + * collectd: Added the `filter chain' infrastructure, which allows the + user to use `matches' and `targets' to control value processing. + * collectd: The new `-T' command line argument allows more in-depth + testing of a configuration. Thanks to Doug MacEachern for the patch. + * collectd-nagios: The Nagios integration command has been updated to + use libcollectdclient. The `percentage' aggregation function has + been added. Thanks to Fabian Linzberger for the patch. + * libcollectdclient: A library which abstracts communication with the + unixsock plugin for clients has been added. + * regex match: Match values by their identifies using regular + expressions. + * timediff match: Match for values with an invalid timestamp. + * value match: Select values by their data sources' values. + * notification target: Create and dispatch a notification. + * replace target: Replace parts of an identifier using regular + expressions. + * set target: Set (overwrite) entire parts of an identifier. + * bind plugin: This new plugin uses the new HTTP/XML interface to BIND + statistics, allowing very detailed name server statistics. Thanks to + Bruno Prémont for this plugin. + * cpu plugin: Report `interrupt' separately when using + sysctlbyname(3) (used under *BSD). Support for sysctl(3), for + example for native OpenBSD support, has been added. Thanks to Simon + Kuhnle for the patch. + * csv plugin: Make it possible to write values to STDOUT instead of + files. This is meant for testing purposes mostly. The output written + to STDOUT is compatible with the exec plugin. Thanks to Doug + MacEachern for the patch. + * curl plugin: This new plugin can be used to read web pages and parse + them using the same mechanism that's used in the tail plugin. + * dbi plugin: This new plugin allows you to connect to a variety of + relational databases and use SQL to gather custom statistics from + it. It is similar to the already existing PostgreSQL plugin but uses + libdbi to communicate with the database(s). + * interface plugin: Use the ignorelist framework when selecting / + ignoring interfaces. This allows one to use regular expressions to + select interfaces, too. + * ipmi plugin: Handle temporary IPMI error conditions more gracefully. + Thanks to Bruno Prémont for this patch. + * memcached plugin: Add hit-ratio metric. Thanks to Doug MacEachern + for the patch. + * mysql plugin: Allow connecting to a database via the UNIX domain + socket, too. Thanks to Mirko Buffoni for the patch. + * network plugin: Further performance improvements for the receive + code. This hopefully will help very large setups. + * openvpn plugin: This new plugin collects statistics provided by the + OpenVPN daemon. Thanks to Doug MacEachern for the patch. + * oracle plugin: This new plugin allows you to connect to an Oracle + database and use SQL to gather custom statistics from it. It is + similar to the already existing PostgreSQL plugin. + * perl plugin: Compatibility fixes for broken versions of Perl 5.10 + have been added. + * perl plugin: Export the newly added plugin_write() to Perl plugins. + * perl plugin: Added support for `notification meta data'. + * perl plugin: Added support for the `filter chain' infrastructure by + allowing plugins to register `matches' and `targets'. + * postgresql plugin: The preferred configuration syntax has been + updated to be in line with the syntax used by the new dbi and oracle + plugins. The compatibility code for the old syntax is present. + Support for the new `Result' blocks and the interval parameter has + been added. + * processes plugin: Stacksize and virtual memory usage statistics have + been added. Portability fixes. + * rrdcached plugin: This new plugin uses the (still in development) + RRD accelerator daemon, rrdcached. This daemon works very similar to + the original rrdtool plugin of collectd, but adds some more nice + features. + * swap plugin: Code for OpenBSD (and possibly other *BSDs) has been + added. + 2009-02-22, Version 4.5.3 * build system: The check for libupsclient even when `pkg-config' is not available. diff --git a/README b/README index 539574a2..b6417411 100644 --- a/README +++ b/README @@ -33,6 +33,13 @@ Features Batterycharge, -current and voltage of ACPI and PMU based laptop batteries. + - curl + Parse statistics from websites using regular expressions. + + - bind + Name server and resolver statistics from the `statistics-channel' + interface of BIND 9.5, 9,6 and later. + - cpu CPU utilization: Time spent in the system, user, nice, idle, and related states. @@ -40,6 +47,10 @@ Features - cpufreq CPU frequency (For laptops with speed step or a similar technology) + - dbi + Executes SQL statements on various databases and interprets the returned + data. + - df Mountpoint usage (Basically the values `df(1)' delivers) @@ -76,6 +87,9 @@ Features Iptables' counters: Number of bytes that were matched by a certain iptables rule. + - ipmi + IPMI (Intelligent Platform Management Interface) sensors information. + - ipvs IPVS connection statistics (number of connections, octets and packets for each service and destination). @@ -139,6 +153,13 @@ Features Read onewire sensors using the owcapu library of the owfs project. Please read in collectd.conf(5) why this plugin is experimental. + - openvpn + RX and TX of each client in openvpn-status.log (status-version 2). + + + - oracle + Query data from an Oracle database. + - perl The perl plugin implements a Perl-interpreter into collectd. You can write your own plugins in Perl and return arbitrary values using this @@ -152,9 +173,15 @@ Features PostgreSQL database statistics: active server connections, transaction numbers, block IO, table row manipulations. + - powerdns + PowerDNS name server statistics. + - processes Process counts: Number of running, sleeping, zombie, ... processes. + - rrdcached + RRDtool caching daemon (RRDcacheD) statistics. + - sensors System sensors, accessed using lm_sensors: Voltages, temperatures and fan rotation speeds. @@ -180,6 +207,12 @@ Features - tcpconns Number of TCP connections to specific local and remote ports. + - teamspeak2 + TeamSpeak2 server statistics. + + - thermal + Linux ACPI thermal zone information. + - users Users currently logged in. @@ -214,6 +247,11 @@ Features you can easily do weird stuff with the plugins we didn't dare think of ;) See collectd-perl(5). + - rrdcached + Output to round-robin-database (RRD) files using the RRDtool caching + daemon (RRDcacheD) - see rrdcached(1). That daemon provides a general + implementation of the caching done by the `rrdtool' plugin. + - rrdtool Output to round-robin-database (RRD) files using librrd. See rrdtool(1). This is likely the most popular destination for such values. Since @@ -265,6 +303,27 @@ Features Notifications are propagated to plugins written in Perl as well. See collectd-perl(5). + * Value processing can be controlled using the "filter chain" infrastructure + and "matches" and "targets". The following plugins are available: + + - match_regex + Match values by their identifier based on regular expressions. + + - match_timediff + Match values with an invalid timestamp. + + - match_value + Select values by their data sources' values. + + - target_notification + Create and dispatch a notification. + + - target_replace + Replace parts of an identifier using regular expressions. + + - target_set + Set (overwrite) entire parts of an identifier. + * Miscellaneous plugins: - uuid @@ -279,7 +338,7 @@ Features since collectd is programmed multithreaded it benefits from hyperthreading and multicore processors and makes sure that the daemon isn't idle if only one plugins waits for an IO-operation to complete. - + * Once set up, hardly any maintenance is necessary. Setup is kept as easy as possible and the default values should be okay for most users. @@ -339,76 +398,104 @@ Prerequisites * CoreFoundation.framework and IOKit.framework (optional) For compiling on Darwin in general and the `apple_sensors' plugin in particular. + + + * libclntsh (optional) + Used by the `oracle' plugin. * libcurl (optional) - If you want to use the `apache', `ascent', or `nginx' plugin. + If you want to use the `apache', `ascent', `curl' or `nginx' plugin. + + + * libdbi (optional) + Used by the `dbi' plugin to connect to various databases. + * libesmtp (optional) For the `notify_email' plugin. + * libhal (optional) If present, the uuid plugin will check for UUID from HAL. + - * libiptc (optional) + * libiptc (optional, if not found a version shipped with this distribution + can be used if the Linux kernel headers are available) For querying iptables counters. + * libmysqlclient (optional) Unsurprisingly used by the `mysql' plugin. + * libnetlink (optional) Used, obviously, for the `netlink' plugin. + * libnetsnmp (optional) For the `snmp' plugin. + * libnotify (optional) For the `notify_desktop' plugin. + * liboping (optional, if not found a version shipped with this distribution can be used) Used by the `ping' plugin to send and receive ICMP packets. + * libowcapi (optional) Used by the `onewire' plugin to read values from onewire sensors (or the owserver(1) daemon). + * libpcap (optional) Used to capture packets by the `dns' plugin. + * libperl (optional) Obviously used by the `perl' plugin. The library has to be compiled with ithread support (introduced in Perl 5.6.0). + * libpq (optional) The PostgreSQL C client library used by the `postgresql' plugin. + - * librrd (optional; headers and library; rrdtool 1.0 and 1.2 both work fine) - If built without `librrd' the resulting binary will be `client only', i.e. - will send its values via multicast and not create any RRD files itself. - Alternatively you can chose to write CSV-files (Comma Separated Values) - instead. + * librrd (optional) + Used by the `rrdtool' and `rrdcached' plugins. The latter requires RRDtool + client support which was added after version 1.3 of RRDtool. Versions 1.0, + 1.2 and 1.3 are known to work with the `rrdtool' plugin. + * librt, libsocket, libkstat, libdevinfo (optional) Various standard Solaris libraries which provide system functions. + * libsensors (optional) To read from `lm_sensors', see the `sensors' plugin. + - * libstatgrab (optional) may be used to collect statistics on systems other - than Linux and/or Solaris. Note that CPU- and disk-statistics, while being - provided by this library, are not supported in collectd right now.. - + * libstatgrab (optional) + Used by various plugins to collect statistics on systems other than Linux + and/or Solaris. + * libupsclient/nut (optional) For the `nut' plugin which queries nut's `upsd'. + * libvirt (optional) Collect statistics from virtual machines. + * libxml2 (optional) Parse XML data. This is needed for the `ascent' and `libvirt' plugins. + * libxmms (optional) + Configuring / Compiling / Installing @@ -418,7 +505,7 @@ Configuring / Compiling / Installing `./configure && make && make install'. For detailed, generic instructions see INSTALL. For a complete list of configure options and their description, run `./configure --help'. - + By default, the configure script will check for all build dependencies and disable all plugins whose requirements cannot be fulfilled (any other plugin will be enabled). To enable a plugin, install missing dependencies (see diff --git a/TODO b/TODO index b5cd6b50..3c8f49eb 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ -* Parse options/identifiers with spaces in them correctly. -* Figure out what to do with the onewire plugin. +* Finalize the onewire plugin. * Custom notification messages? +* Implement moving-average calculation for the threshold stuff. src/battery.c: commend not working code. @@ -10,6 +10,7 @@ Wishlist: - be free of syntax errors. * Port nfs module to solaris * Port tape module to Linux +* Port the apple_sensors plugin to Linux/PPC. * Maybe look into porting the serial module * Build Darwin package * Maybe let the network plugin configure whether or not notifications should be diff --git a/bindings/perl/Collectd.pm b/bindings/perl/Collectd.pm index 738206bb..557950cb 100644 --- a/bindings/perl/Collectd.pm +++ b/bindings/perl/Collectd.pm @@ -1,5 +1,5 @@ # collectd - Collectd.pm -# Copyright (C) 2007, 2008 Sebastian Harl +# Copyright (C) 2007-2009 Sebastian Harl # # 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 @@ -42,6 +42,7 @@ our %EXPORT_TAGS = ( plugin_register plugin_unregister plugin_dispatch_values + plugin_write plugin_flush plugin_flush_one plugin_flush_all @@ -75,6 +76,18 @@ our %EXPORT_TAGS = ( LOG_INFO LOG_DEBUG ) ], + 'filter_chain' => [ qw( + fc_register + FC_MATCH_NO_MATCH + FC_MATCH_MATCHES + FC_TARGET_CONTINUE + FC_TARGET_STOP + FC_TARGET_RETURN + ) ], + 'fc_types' => [ qw( + FC_MATCH + FC_TARGET + ) ], 'notif' => [ qw( NOTIF_FAILURE NOTIF_WARNING @@ -99,6 +112,7 @@ our $interval_g; Exporter::export_ok_tags ('all'); my @plugins : shared = (); +my @fc_plugins : shared = (); my %cf_callbacks : shared = (); my %types = ( @@ -111,10 +125,24 @@ my %types = ( TYPE_FLUSH, "flush" ); +my %fc_types = ( + FC_MATCH, "match", + FC_TARGET, "target" +); + +my %fc_exec_names = ( + FC_MATCH, "match", + FC_TARGET, "invoke" +); + foreach my $type (keys %types) { $plugins[$type] = &share ({}); } +foreach my $type (keys %fc_types) { + $fc_plugins[$type] = &share ({}); +} + sub _log { my $caller = shift; my $lvl = shift; @@ -318,6 +346,66 @@ sub plugin_unregister { } } +sub plugin_write { + my %args = @_; + + my @plugins = (); + my @datasets = (); + my @valuelists = (); + + if (! defined $args{'valuelists'}) { + ERROR ("Collectd::plugin_write: Missing 'valuelists' argument."); + return; + } + + DEBUG ("Collectd::plugin_write:" + . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "") + . (defined ($args{'datasets'}) ? " datasets = $args{'datasets'}" : "") + . " valueslists = $args{'valuelists'}"); + + if (defined ($args{'plugins'})) { + if ("ARRAY" eq ref ($args{'plugins'})) { + @plugins = @{$args{'plugins'}}; + } + else { + @plugins = ($args{'plugins'}); + } + } + else { + @plugins = (undef); + } + + if ("ARRAY" eq ref ($args{'valuelists'})) { + @valuelists = @{$args{'valuelists'}}; + } + else { + @valuelists = ($args{'valuelists'}); + } + + if (defined ($args{'datasets'})) { + if ("ARRAY" eq ref ($args{'datasets'})) { + @datasets = @{$args{'datasets'}}; + } + else { + @datasets = ($args{'datasets'}); + } + } + else { + @datasets = (undef) x scalar (@valuelists); + } + + if ($#datasets != $#valuelists) { + ERROR ("Collectd::plugin_write: Invalid number of datasets."); + return; + } + + foreach my $plugin (@plugins) { + for (my $i = 0; $i < scalar (@valuelists); ++$i) { + _plugin_write ($plugin, $datasets[$i], $valuelists[$i]); + } + } +} + sub plugin_flush { my %args = @_; @@ -395,6 +483,141 @@ sub plugin_flush_all { plugin_flush (timeout => $timeout); } +sub fc_call { + my $type = shift; + my $name = shift; + my $cb_type = shift; + + my %proc; + + our $cb_name = undef; + my $status; + + if (! ((defined $type) && (defined $name) && (defined $cb_type))) { + ERROR ("Usage: Collectd::fc_call(type, name, cb_type, ...)"); + return; + } + + if (! defined $fc_plugins[$type]) { + ERROR ("Collectd::fc_call: Invalid type \"$type\""); + return; + } + + if (! defined $fc_plugins[$type]->{$name}) { + ERROR ("Collectd::fc_call: Unknown " + . ($type == FC_MATCH ? "match" : "target") + . " \"$name\""); + return; + } + + DEBUG ("Collectd::fc_call: " + . "type = \"$type\", name = \"$name\", cb_type = \"$cb_type\""); + + { + lock %{$fc_plugins[$type]}; + %proc = %{$fc_plugins[$type]->{$name}}; + } + + if (FC_CB_EXEC == $cb_type) { + $cb_name = $proc{$fc_exec_names{$type}}; + } + elsif (FC_CB_CREATE == $cb_type) { + if (defined $proc{'create'}) { + $cb_name = $proc{'create'}; + } + else { + return 1; + } + } + elsif (FC_CB_DESTROY == $cb_type) { + if (defined $proc{'destroy'}) { + $cb_name = $proc{'destroy'}; + } + else { + return 1; + } + } + + $status = call_by_name (@_); + + if ($status < 0) { + my $err = undef; + + if ($@) { + $err = $@; + } + else { + $err = "callback returned false"; + } + + ERROR ("Execution of fc callback \"$cb_name\" failed: $err"); + return; + } + return $status; +} + +sub fc_register { + my $type = shift; + my $name = shift; + my $proc = shift; + + my %fc : shared; + + DEBUG ("Collectd::fc_register: " + . "type = \"$type\", name = \"$name\", proc = \"$proc\""); + + if (! ((defined $type) && (defined $name) && (defined $proc))) { + ERROR ("Usage: Collectd::fc_register(type, name, proc)"); + return; + } + + if (! defined $fc_plugins[$type]) { + ERROR ("Collectd::fc_register: Invalid type \"$type\""); + return; + } + + if (("HASH" ne ref ($proc)) || (! defined $proc->{$fc_exec_names{$type}}) + || ("" ne ref ($proc->{$fc_exec_names{$type}}))) { + ERROR ("Collectd::fc_register: Invalid proc."); + return; + } + + for my $p (qw( create destroy )) { + if ((defined $proc->{$p}) && ("" ne ref ($proc->{$p}))) { + ERROR ("Collectd::fc_register: Invalid proc."); + return; + } + } + + %fc = %$proc; + + foreach my $p (keys %fc) { + my $pkg = scalar caller; + + if ($p !~ m/^(create|destroy|$fc_exec_names{$type})$/) { + next; + } + + if ($fc{$p} !~ m/^$pkg\:\:/) { + $fc{$p} = $pkg . "::" . $fc{$p}; + } + } + + lock %{$fc_plugins[$type]}; + if (defined $fc_plugins[$type]->{$name}) { + WARNING ("Collectd::fc_register: Overwriting previous " + . "definition of match \"$name\"."); + } + + if (! _fc_register ($type, $name)) { + ERROR ("Collectd::fc_register: Failed to register \"$name\"."); + return; + } + + $fc_plugins[$type]->{$name} = \%fc; + return 1; +} + sub _plugin_dispatch_config { my $plugin = shift; my $config = shift; diff --git a/build.sh b/build.sh index 3822c2bc..804b2e25 100755 --- a/build.sh +++ b/build.sh @@ -25,20 +25,24 @@ check_for_application lex yacc autoheader aclocal automake autoconf check_for_application pkg-config libtoolize="" -if which libtoolize >/dev/null 2>&1 +libtoolize --version >/dev/null 2>/dev/null +if test $? -eq 0 then libtoolize=libtoolize -else if which glibtoolize >/dev/null 2>&1 -then - libtoolize=glibtoolize else - cat >&2 </dev/null 2>/dev/null + if test $? -eq 0 + then + libtoolize=glibtoolize + else + cat >&2 < #include -#include #include +#if HAVE_STDINT_H +# include +#endif +#if HAVE_STDBOOL_H +# include +#endif ]]]], [[[[ uint64_t i0; @@ -668,8 +679,13 @@ if test "x$fp_layout_type" = "xunknown"; then [[[[ #include #include -#include #include +#if HAVE_STDINT_H +# include +#endif +#if HAVE_STDBOOL_H +# include +#endif #define endianflip(A) ((((uint64_t)(A) & 0xff00000000000000LL) >> 56) | \ (((uint64_t)(A) & 0x00ff000000000000LL) >> 40) | \ (((uint64_t)(A) & 0x0000ff0000000000LL) >> 24) | \ @@ -715,8 +731,13 @@ if test "x$fp_layout_type" = "xunknown"; then [[[[ #include #include -#include #include +#if HAVE_STDINT_H +# include +#endif +#if HAVE_STDBOOL_H +# include +#endif #define intswap(A) ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \ (((uint64_t)(A) & 0x00000000ffffffffLL) << 32)) ]]]], @@ -970,102 +991,6 @@ fi m4_divert_once([HELP_WITH], [ collectd additional packages:]) -# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given]) -librrd_cflags="" -librrd_ldflags="" -librrd_threadsafe="yes" -AC_ARG_WITH(rrdtool, [AS_HELP_STRING([--with-rrdtool@<:@=PREFIX@:>@], [Path to rrdtool.])], -[ if test "x$withval" != "xno" && test "x$withval" != "xyes" - then - librrd_cflags="-I$withval/include" - librrd_ldflags="-L$withval/lib" - with_rrdtool="yes" - else - with_rrdtool="$withval" - fi -], [with_rrdtool="yes"]) -if test "x$with_rrdtool" = "xyes" -then - SAVE_CPPFLAGS="$CPPFLAGS" - SAVE_LDFLAGS="$LDFLAGS" - - CPPFLAGS="$CPPFLAGS $librrd_cflags" - LDFLAGS="$LDFLAGS $librrd_ldflags" - - AC_CHECK_HEADERS(rrd.h,, [with_rrdtool="no (rrd.h not found)"]) - - CPPFLAGS="$SAVE_CPPFLAGS" - LDFLAGS="$SAVE_LDFLAGS" -fi -if test "x$with_rrdtool" = "xyes" -then - SAVE_CPPFLAGS="$CPPFLAGS" - SAVE_LDFLAGS="$LDFLAGS" - - CPPFLAGS="$CPPFLAGS $librrd_cflags" - LDFLAGS="$LDFLAGS $librrd_ldflags" - - AC_CHECK_LIB(rrd_th, rrd_update_r, - [with_rrdtool="yes" - librrd_ldflags="$librrd_ldflags -lrrd_th -lm" - ], - [librrd_threadsafe="no" - AC_CHECK_LIB(rrd, rrd_update, - [with_rrdtool="yes" - librrd_ldflags="$librrd_ldflags -lrrd -lm" - ], - [with_rrdtool="no (symbol 'rrd_update' not found)"], - [-lm]) - ], - [-lm]) - - CPPFLAGS="$SAVE_CPPFLAGS" - LDFLAGS="$SAVE_LDFLAGS" -fi -if test "x$with_rrdtool" = "xyes" -then - BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags" - BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags" - AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS) - AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS) -fi -if test "x$librrd_threadsafe" = "xyes" -then - AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).]) -fi - -AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])], -[ if test "x$withval" != "xno" \ - && test "x$withval" != "xyes" - then - LDFLAGS="$LDFLAGS -L$withval/lib" - CPPFLAGS="$CPPFLAGS -I$withval/include" - with_libpthread="yes" - else - if test "x$withval" = "xno" - then - with_libpthread="no (disabled)" - fi - fi -], [with_libpthread="yes"]) -if test "x$with_libpthread" = "xyes" -then - AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], []) -fi -if test "x$with_libpthread" = "xyes" -then - AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"]) -fi -if test "x$with_libpthread" = "xyes" -then - collect_pthread=1 -else - collect_pthread=0 -fi -AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread], - [Wether or not to use pthread (POSIX threads) library]) -AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes") - if test "x$ac_system" = "xSolaris" then with_kstat="yes" @@ -1092,7 +1017,54 @@ fi AM_CONDITIONAL(BUILD_WITH_LIBKSTAT, test "x$with_kstat" = "xyes") AM_CONDITIONAL(BUILD_WITH_LIBDEVINFO, test "x$with_devinfo" = "xyes") -### BEGIN of check for libcurl ### +with_libiokit="no" +AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices, +[ + with_libiokit="yes" +], +[ + with_libiokit="no" +]) +AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes") + +with_libkvm="no" +AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"]) +if test "x$with_kvm_getprocs" = "xyes" +then + AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1, + [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)]) + with_libkvm="yes" +fi +AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes") + +AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"]) +if test "x$with_kvm_getswapinfo" = "xyes" +then + AC_DEFINE(HAVE_LIBKVM_GETSWAPINFO, 1, + [Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol (-lkvm)]) + with_libkvm="yes" +fi +AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes") + +AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"]) +if test "x$with_kvm_nlist" = "xyes" +then + AC_DEFINE(HAVE_LIBKVM_NLIST, 1, + [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)]) + with_libkvm="yes" +fi +AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes") + +AC_CHECK_LIB(kvm, kvm_openfiles, [with_kvm_openfiles="yes"], [with_kvm_openfiles="no"]) +if test "x$with_kvm_openfiles" = "xyes" +then + AC_DEFINE(HAVE_LIBKVM_NLIST, 1, + [Define to 1 if you have the 'kvm' library with the 'kvm_openfiles' symbol (-lkvm)]) + with_libkvm="yes" +fi +AM_CONDITIONAL(BUILD_WITH_LIBKVM_OPENFILES, test "x$with_kvm_openfiles" = "xyes") + +# --with-libcurl {{{ with_curl_config="curl-config" with_curl_cflags="" with_curl_libs="" @@ -1160,230 +1132,166 @@ then AC_SUBST(BUILD_WITH_LIBCURL_LIBS) fi AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes") -### END of check for libcurl ### - -with_libiokit="no" -AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices, -[ - with_libiokit="yes" -], -[ - with_libiokit="no" -]) -AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes") +# }}} -with_libstatgrab_cflags="" -with_libstatgrab_ldflags="" -AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])], +# --with-libdbi {{{ +with_libdbi_cppflags="" +with_libdbi_ldflags="" +AC_ARG_WITH(libdbi, [AS_HELP_STRING([--with-libdbi@<:@=PREFIX@:>@], [Path to libdbi.])], [ - if test "x$withval" != "xno" \ - && test "x$withval" != "xyes" + if test "x$withval" != "xno" && test "x$withval" != "xyes" then - with_libstatgrab_cflags="-I$withval/include" - with_libstatgrab_ldflags="-L$withval/lib" - with_libstatgrab="yes" + with_libdbi_cppflags="-I$withval/include" + with_libdbi_ldflags="-L$withval/lib" + with_libdbi="yes" else - with_libstatgrab="$withval" + with_libdbi="$withval" fi ], [ - if test "x$ac_system" = "xunknown" - then - with_libstatgrab="yes" - else - with_libstatgrab="no" - fi + with_libdbi="yes" ]) -with_libstatgrab_pkg_config="yes" -if test "x$with_libstatgrab" = "xyes" \ - && test "x$PKG_CONFIG" != "x" +if test "x$with_libdbi" = "xyes" then - AC_MSG_CHECKING([pkg-config for libstatgrab]) - temp_result="found" - $PKG_CONFIG --exists libstatgrab 2>/dev/null - if test "$?" != "0" - then - with_libstatgrab_pkg_config="no" - temp_result="not found" - fi - AC_MSG_RESULT([$temp_result]) -else - AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.]) - with_libstatgrab_pkg_config="no" - with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab" -fi + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags" -if test "x$with_libstatgrab" = "xyes" \ - && test "x$with_libstatgrab_pkg_config" = "xyes" \ - && test "x$with_libstatgrab_cflags" = "x" -then - AC_MSG_CHECKING([for libstatgrab CFLAGS]) - temp_result="`$PKG_CONFIG --cflags libstatgrab`" - if test "$?" = "0" - then - with_libstatgrab_cflags="$temp_result" - else - with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)" - temp_result="$PKG_CONFIG --cflags libstatgrab failed" - fi - AC_MSG_RESULT([$temp_result]) -fi + AC_CHECK_HEADERS(dbi/dbi.h, [with_libdbi="yes"], [with_libdbi="no (dbi/dbi.h not found)"]) -if test "x$with_libstatgrab" = "xyes" \ - && test "x$with_libstatgrab_pkg_config" = "xyes" \ - && test "x$with_libstatgrab_ldflags" = "x" -then - AC_MSG_CHECKING([for libstatgrab LDFLAGS]) - temp_result="`$PKG_CONFIG --libs libstatgrab`" - if test "$?" = "0" - then - with_libstatgrab_ldflags="$temp_result" - else - with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)" - temp_result="$PKG_CONFIG --libs libstatgrab failed" - fi - AC_MSG_RESULT([$temp_result]) + CPPFLAGS="$SAVE_CPPFLAGS" fi - -if test "x$with_libstatgrab" = "xyes" +if test "x$with_libdbi" = "xyes" then - SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags" + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags" + LDFLAGS="$LDFLAGS $with_libdbi_ldflags" - AC_CHECK_HEADERS(statgrab.h, - [with_libstatgrab="yes"], - [with_libstatgrab="no (statgrab.h not found)"]) + AC_CHECK_LIB(dbi, dbi_initialize, [with_libdbi="yes"], [with_libdbi="no (Symbol 'dbi_initialize' not found)"]) - CPPFLAGS="$SAVE_CPPFLAGS" + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" fi - -if test "x$with_libstatgrab" = "xyes" +if test "x$with_libdbi" = "xyes" then - SAVE_CFLAGS="$CFLAGS" - SAVE_LDFLAGS="$LDFLAGS" - - CFLAGS="$CFLAGS $with_libstatgrab_cflags" - LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags" - - AC_CHECK_LIB(statgrab, sg_init, - [with_libstatgrab="yes"], - [with_libstatgrab="no (symbol sg_init not found)"]) - - CFLAGS="$SAVE_CFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + BUILD_WITH_LIBDBI_CPPFLAGS="$with_libdbi_cppflags" + BUILD_WITH_LIBDBI_LDFLAGS="$with_libdbi_ldflags" + BUILD_WITH_LIBDBI_LIBS="-ldbi" + AC_SUBST(BUILD_WITH_LIBDBI_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBDBI_LDFLAGS) + AC_SUBST(BUILD_WITH_LIBDBI_LIBS) fi +AM_CONDITIONAL(BUILD_WITH_LIBDBI, test "x$with_libdbi" = "xyes") +# }}} -AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes") -if test "x$with_libstatgrab" = "xyes" +# --with-libesmtp {{{ +AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + LDFLAGS="$LDFLAGS -L$withval/lib" + CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE" + with_libesmtp="yes" + else + with_libesmtp="$withval" + fi +], +[ + with_libesmtp="yes" +]) +if test "x$with_libesmtp" = "xyes" then - AC_DEFINE(HAVE_LIBSTATGRAB, 1, [Define to 1 if you have the 'statgrab' library (-lstatgrab)]) - BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags" - BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags" - AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS) - AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS) + AC_CHECK_LIB(esmtp, smtp_create_session, + [ + AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).]) + ], [with_libesmtp="no (libesmtp not found)"]) fi - -with_libkvm="no" -AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"]) -if test "x$with_kvm_getprocs" = "xyes" +if test "x$with_libesmtp" = "xyes" then - AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1, - [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)]) - with_libkvm="yes" -fi -AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes") - -AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"]) -if test "x$with_kvm_getswapinfo" = "xyes" -then - AC_DEFINE(HAVE_LIBKVM_GETSWAPINFO, 1, - [Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol (-lkvm)]) - with_libkvm="yes" -fi -AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes") - -AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"]) -if test "x$with_kvm_nlist" = "xyes" -then - AC_DEFINE(HAVE_LIBKVM_NLIST, 1, - [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)]) - with_libkvm="yes" + AC_CHECK_HEADERS(libesmtp.h, + [ + AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the header file.]) + ], [with_libesmtp="no (libesmtp.h not found)"]) fi -AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes") - -AC_CHECK_LIB(kvm, kvm_openfiles, [with_kvm_openfiles="yes"], [with_kvm_openfiles="no"]) -if test "x$with_kvm_openfiles" = "xyes" +if test "x$with_libesmtp" = "xyes" then - AC_DEFINE(HAVE_LIBKVM_NLIST, 1, - [Define to 1 if you have the 'kvm' library with the 'kvm_openfiles' symbol (-lkvm)]) - with_libkvm="yes" + collect_libesmtp=1 +else + collect_libesmtp=0 fi -AM_CONDITIONAL(BUILD_WITH_LIBKVM_OPENFILES, test "x$with_kvm_openfiles" = "xyes") +AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp], + [Wether or not to use the esmtp library]) +AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes") +# }}} -with_sensors_cflags="" -with_sensors_ldflags="" -AC_ARG_WITH(lm-sensors, [AS_HELP_STRING([--with-lm-sensors@<:@=PREFIX@:>@], [Path to lm_sensors.])], +# --with-libiptc {{{ +with_own_libiptc="no" +AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])], [ - if test "x$withval" = "xno" + if test "x$withval" != "xno" && test "x$withval" != "xyes" then - with_lm_sensors="no" + LDFLAGS="$LDFLAGS -L$withval/lib" + CPPFLAGS="$CPPFLAGS -I$withval/include" + with_libiptc="yes" else - with_lm_sensors="yes" - if test "x$withval" != "xyes" - then - with_sensors_cflags="-I$withval/include" - with_sensors_ldflags="-L$withval/lib" - with_lm_sensors="yes" - fi + with_libiptc="$withval" fi ], [ if test "x$ac_system" = "xLinux" then - with_lm_sensors="yes" + with_libiptc="yes" else - with_lm_sensors="no (Linux only library)" + with_libiptc="no (Linux only)" fi ]) -if test "x$with_lm_sensors" = "xyes" +if test "x$with_libiptc" = "xyes" then - SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_sensors_cflags" - -# AC_CHECK_HEADERS(sensors/sensors.h, -# [ -# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the header file.]) -# ], -# [with_lm_sensors="no (sensors/sensors.h not found)"]) - AC_CHECK_HEADERS(sensors/sensors.h, [], [with_lm_sensors="no (sensors/sensors.h not found)"]) - - CPPFLAGS="$SAVE_CPPFLAGS" + AC_CHECK_LIB(iptc, iptc_init, + [ + AC_DEFINE(HAVE_LIBIPTC, 1, [Define to 1 if you have the iptc library (-liptc).]) + ], + [ + with_libiptc="yes" + with_own_libiptc="yes" + ]) fi -if test "x$with_lm_sensors" = "xyes" +if test "x$with_libiptc" = "xyes" -a "x$with_own_libiptc" != "xyes" then - SAVE_CPPFLAGS="$CPPFLAGS" - SAVE_LDFLAGS="$LDFLAGS" - CPPFLAGS="$CPPFLAGS $with_sensors_cflags" - LDFLAGS="$LDFLAGS $with_sensors_ldflags" + AC_CHECK_HEADERS(libiptc/libiptc.h, + [ + AC_DEFINE(HAVE_LIBIPTC_LIBIPTC_H, 1, [Define to 1 if you have the header file.]) + ], + [ + with_libiptc="yes" + with_own_libiptc="yes" + ]) +fi +if test "x$with_libiptc" = "xyes" +then + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $KERNEL_CFLAGS" - AC_CHECK_LIB(sensors, sensors_init, + AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h, [], [ - AC_DEFINE(HAVE_LIBSENSORS, 1, [Define to 1 if you have the sensors library (-lsensors).]) + with_libiptc="no (Linux iptables headers not found - check KERNEL_DIR)" + with_own_libiptc="no" ], - [with_lm_sensors="no (libsensors not found)"]) + [ +#include "$srcdir/src/libiptc/ipt_kernel_headers.h" + ]) - CPPFLAGS="$SAVE_CPPFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + CFLAGS=$SAVE_CFLAGS fi -if test "x$with_lm_sensors" = "xyes" +AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes") +AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_own_libiptc" = "xyes") +if test "x$with_own_libiptc" = "xyes" then - BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags" - BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags" - AC_SUBST(BUILD_WITH_LIBSENSORS_CFLAGS) - AC_SUBST(BUILD_WITH_LIBSENSORS_LDFLAGS) + AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.]) fi -AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_lm_sensors" = "xyes") +# }}} +# --with-libmysql {{{ with_mysql_config="mysql_config" with_mysql_cflags="" with_mysql_libs="" @@ -1466,63 +1374,238 @@ then AC_SUBST(BUILD_WITH_LIBMYSQL_LIBS) fi AM_CONDITIONAL(BUILD_WITH_LIBMYSQL, test "x$with_libmysql" = "xyes") +# }}} -with_own_liboconfig="no" -liboconfig_LDFLAGS="$LDFLAGS" -liboconfig_CPPFLAGS="$CPPFLAGS" -AC_ARG_WITH(liboconfig, [AS_HELP_STRING([--with-liboconfig@<:@=PREFIX@:>@], [Path to liboconfig.])], +# --with-libnetlink {{{ +with_libnetlink_cflags="" +with_libnetlink_libs="-lnetlink" +AC_ARG_WITH(libnetlink, [AS_HELP_STRING([--with-libnetlink@<:@=PREFIX@:>@], [Path to libnetlink.])], [ - if test "x$withval" != "xno" && test "x$withval" != "xyes" - then - if test -d "$withval/lib" - then - liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib" - fi - if test -d "$withval/include" - then - liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include" - fi - fi - if test "x$withval" = "xno" - then - AC_MSG_ERROR("liboconfig is required") - fi + echo "libnetlink: withval = $withval" + if test "x$withval" = "xyes" + then + with_libnetlink="yes" + else if test "x$withval" = "xno" + then + with_libnetlink="no" + else + if test -d "$withval/include" + then + with_libnetlink_cflags="-I$withval/include" + with_libnetlink_libs="-L$withval/lib -lnetlink" + with_libnetlink="yes" + else + AC_MSG_ERROR("no such directory: $withval/include") + fi + fi; fi ], [ - with_liboconfig="yes" + if test "x$ac_system" = "xLinux" + then + with_libnetlink="yes" + else + with_libnetlink="no (Linux only library)" + fi ]) +if test "x$with_libnetlink" = "xyes" +then + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $with_libnetlink_cflags" -save_LDFLAGS="$LDFLAGS" -save_CPPFLAGS="$CPPFLAGS" -LDFLAGS="$liboconfig_LDFLAGS" -CPPFLAGS="$liboconfig_CPPFLAGS" -AC_CHECK_LIB(oconfig, oconfig_parse_fh, -[ - with_liboconfig="yes" - with_own_liboconfig="no" -], -[ - with_liboconfig="yes" - with_own_liboconfig="yes" - LDFLAGS="$save_LDFLAGS" - CPPFLAGS="$save_CPPFLAGS" -]) + with_libnetlink="no (libnetlink.h not found)" -AM_CONDITIONAL(BUILD_WITH_OWN_LIBOCONFIG, test "x$with_own_liboconfig" = "xyes") -if test "x$with_own_liboconfig" = "xyes" + AC_CHECK_HEADERS(libnetlink.h iproute/libnetlink.h linux/libnetlink.h, + [ + with_libnetlink="yes" + break + ], [], +[#include +#include +#include +#include +#include +#include ]) + AC_CHECK_HEADERS(linux/gen_stats.h linux/pkt_sched.h, [], [], +[#include +#include +#include +#include ]) + + AC_COMPILE_IFELSE( +[#include +#include +#include +#include +#include +#include + +int main (void) +{ + int retval = TCA_STATS2; + return (retval); +}], + [AC_DEFINE([HAVE_TCA_STATS2], 1, [True if the enum-member TCA_STATS2 exists])] + []); + + AC_COMPILE_IFELSE( +[#include +#include +#include +#include +#include +#include + +int main (void) +{ + int retval = TCA_STATS; + return (retval); +}], + [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])] + []); + + CFLAGS="$SAVE_CFLAGS" +fi +if test "x$with_libnetlink" = "xyes" then - with_liboconfig="yes (shipped version)" + AC_CHECK_LIB(netlink, rtnl_open, + [with_libnetlink="yes"], + [with_libnetlink="no (symbol 'rtnl_open' not found)"], + [$with_libnetlink_libs]) +fi +if test "x$with_libnetlink" = "xyes" +then + BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags" + BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs" + AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS) + AC_SUBST(BUILD_WITH_LIBNETLINK_LIBS) fi +AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes") +# }}} -#with_liboping="yes" -with_own_liboping="no" -liboping_LDFLAGS="$LDFLAGS" -liboping_CPPFLAGS="$CPPFLAGS" -AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])], +# --with-libnetsnmp {{{ +with_snmp_config="net-snmp-config" +with_snmp_cflags="" +with_snmp_libs="" +AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])], [ - if test "x$withval" != "xno" && test "x$withval" != "xyes" + if test "x$withval" = "xno" then - if test -d "$withval/lib" + with_libnetsnmp="no" + else if test "x$withval" = "xyes" + then + with_libnetsnmp="yes" + else + if test -x "$withval" + then + with_snmp_config="$withval" + with_libnetsnmp="yes" + else + with_snmp_config="$withval/bin/net-snmp-config" + with_libnetsnmp="yes" + fi + fi; fi +], +[with_libnetsnmp="yes"]) +if test "x$with_libnetsnmp" = "xyes" +then + with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null` + snmp_config_status=$? + + if test $snmp_config_status -ne 0 + then + with_libnetsnmp="no ($with_snmp_config failed)" + else + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_snmp_cflags" + + AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + fi +fi +if test "x$with_libnetsnmp" = "xyes" +then + with_snmp_libs=`$with_snmp_config --libs 2>/dev/null` + snmp_config_status=$? + + if test $snmp_config_status -ne 0 + then + with_libnetsnmp="no ($with_snmp_config failed)" + else + AC_CHECK_LIB(netsnmp, init_snmp, + [with_libnetsnmp="yes"], + [with_libnetsnmp="no (libnetsnmp not found)"], + [$with_snmp_libs]) + fi +fi +if test "x$with_libnetsnmp" = "xyes" +then + BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags" + BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs" + AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS) + AC_SUBST(BUILD_WITH_LIBSNMP_LIBS) +fi +AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes") +# }}} + +# --with-liboconfig {{{ +with_own_liboconfig="no" +liboconfig_LDFLAGS="$LDFLAGS" +liboconfig_CPPFLAGS="$CPPFLAGS" +AC_ARG_WITH(liboconfig, [AS_HELP_STRING([--with-liboconfig@<:@=PREFIX@:>@], [Path to liboconfig.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + if test -d "$withval/lib" + then + liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib" + fi + if test -d "$withval/include" + then + liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include" + fi + fi + if test "x$withval" = "xno" + then + AC_MSG_ERROR("liboconfig is required") + fi +], +[ + with_liboconfig="yes" +]) + +save_LDFLAGS="$LDFLAGS" +save_CPPFLAGS="$CPPFLAGS" +LDFLAGS="$liboconfig_LDFLAGS" +CPPFLAGS="$liboconfig_CPPFLAGS" +AC_CHECK_LIB(oconfig, oconfig_parse_fh, +[ + with_liboconfig="yes" + with_own_liboconfig="no" +], +[ + with_liboconfig="yes" + with_own_liboconfig="yes" + LDFLAGS="$save_LDFLAGS" + CPPFLAGS="$save_CPPFLAGS" +]) + +AM_CONDITIONAL(BUILD_WITH_OWN_LIBOCONFIG, test "x$with_own_liboconfig" = "xyes") +if test "x$with_own_liboconfig" = "xyes" +then + with_liboconfig="yes (shipped version)" +fi +# }}} + +# --with-liboping {{{ +with_own_liboping="no" +liboping_LDFLAGS="$LDFLAGS" +liboping_CPPFLAGS="$CPPFLAGS" +AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + if test -d "$withval/lib" then liboping_LDFLAGS="$LDFLAGS -L$withval/lib" fi @@ -1564,7 +1647,78 @@ then fi AM_CONDITIONAL(BUILD_WITH_LIBOPING, test "x$with_liboping" = "xyes") AM_CONDITIONAL(BUILD_WITH_OWN_LIBOPING, test "x$with_own_liboping" = "xyes") +# }}} + +# --with-oracle {{{ +with_oracle_cppflags="" +with_oracle_libs="" +AC_ARG_WITH(oracle, [AS_HELP_STRING([--with-oracle@<:@=ORACLE_HOME@:>@], [Path to Oracle.])], +[ + if test "x$withval" = "xyes" + then + if test "x$ORACLE_HOME" = "x" + then + AC_MSG_WARN([Use of the Oracle library has been forced, but the environment variable ORACLE_HOME is not set.]) + fi + with_oracle="yes" + else if test "x$withval" = "xno" + then + with_oracle="no" + else + with_oracle="yes" + ORACLE_HOME="$withval" + fi; fi +], +[ + if test "x$ORACLE_HOME" = "x" + then + with_oracle="no (ORACLE_HOME is not set)" + else + with_oracle="yes" + fi +]) +if test "x$ORACLE_HOME" != "x" +then + with_oracle_cppflags="-I$ORACLE_HOME/rdbms/public" + if test -e "$ORACLE_HOME/lib/ldflags" + then + with_oracle_libs=`cat "$ORACLE_HOME/lib/ldflags"` + fi + #with_oracle_libs="-L$ORACLE_HOME/lib $with_oracle_libs -lclntsh" + with_oracle_libs="-L$ORACLE_HOME/lib -lclntsh" +fi +if test "x$with_oracle" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_oracle_cppflags" + + AC_CHECK_HEADERS(oci.h, [with_oracle="yes"], [with_oracle="no (oci.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_oracle" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS $with_oracle_cppflags" + LDFLAGS="$LDFLAGS $with_oracle_libs" + + AC_CHECK_FUNC(OCIEnvCreate, [with_oracle="yes"], [with_oracle="no (Symbol 'OCIEnvCreate' not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_oracle" = "xyes" +then + BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags" + BUILD_WITH_ORACLE_LIBS="$with_oracle_libs" + AC_SUBST(BUILD_WITH_ORACLE_CFLAGS) + AC_SUBST(BUILD_WITH_ORACLE_LIBS) +fi +# }}} + +# --with-libowcapi {{{ with_libowcapi_cppflags="" with_libowcapi_libs="-lowcapi" AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])], @@ -1609,8 +1763,9 @@ then AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS) AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS) fi +# }}} - +# --with-libpcap {{{ AC_ARG_WITH(libpcap, [AS_HELP_STRING([--with-libpcap@<:@=PREFIX@:>@], [Path to libpcap.])], [ if test "x$withval" != "xno" && test "x$withval" != "xyes" @@ -1648,45 +1803,9 @@ fi AC_DEFINE_UNQUOTED(COLLECT_LIBPCAP, [$collect_libpcap], [Wether or not to use the pcap library]) AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes") +# }}} -AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])], -[ - if test "x$withval" != "xno" && test "x$withval" != "xyes" - then - LDFLAGS="$LDFLAGS -L$withval/lib" - CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE" - with_libesmtp="yes" - else - with_libesmtp="$withval" - fi -], -[ - with_libesmtp="yes" -]) -if test "x$with_libesmtp" = "xyes" -then - AC_CHECK_LIB(esmtp, smtp_create_session, - [ - AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).]) - ], [with_libesmtp="no (libesmtp not found)"]) -fi -if test "x$with_libesmtp" = "xyes" -then - AC_CHECK_HEADERS(libesmtp.h, - [ - AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the header file.]) - ], [with_libesmtp="no (libesmtp.h not found)"]) -fi -if test "x$with_libesmtp" = "xyes" -then - collect_libesmtp=1 -else - collect_libesmtp=0 -fi -AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp], - [Wether or not to use the esmtp library]) -AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes") - +# --with-libperl {{{ perl_interpreter="perl" AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to libperl.])], [ @@ -1804,611 +1923,653 @@ then LDFLAGS=$SAVE_LDFLAGS fi -with_own_libiptc="no" -AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])], -[ - if test "x$withval" != "xno" && test "x$withval" != "xyes" - then - LDFLAGS="$LDFLAGS -L$withval/lib" - CPPFLAGS="$CPPFLAGS -I$withval/include" - with_libiptc="yes" - else - with_libiptc="$withval" - fi -], -[ - if test "x$ac_system" = "xLinux" - then - with_libiptc="yes" - else - with_libiptc="no (Linux only)" - fi -]) -if test "x$with_libiptc" = "xyes" -then - AC_CHECK_LIB(iptc, iptc_init, - [ - AC_DEFINE(HAVE_LIBIPTC, 1, [Define to 1 if you have the iptc library (-liptc).]) - ], - [ - with_libiptc="yes" - with_own_libiptc="yes" - ]) -fi -if test "x$with_libiptc" = "xyes" -a "x$with_own_libiptc" != "xyes" -then - AC_CHECK_HEADERS(libiptc/libiptc.h, - [ - AC_DEFINE(HAVE_LIBIPTC_LIBIPTC_H, 1, [Define to 1 if you have the header file.]) - ], - [ - with_libiptc="yes" - with_own_libiptc="yes" - ]) -fi -if test "x$with_libiptc" = "xyes" +c_cv_have_broken_perl_load_module="no" +if test "x$with_libperl" = "xyes" then SAVE_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $KERNEL_CFLAGS" + SAVE_LDFLAGS=$LDFLAGS + # trigger an error if Perl_load_module*() uses __attribute__nonnull__(3) + # (see issues #41 and #42) + CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror" + LDFLAGS="$LDFLAGS $PERL_LDFLAGS" - AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h, [], - [ - with_libiptc="no (Linux iptables headers not found - check KERNEL_DIR)" - with_own_libiptc="no" - ], - [ -#include "$srcdir/src/libiptc/ipt_kernel_headers.h" - ]) + AC_CACHE_CHECK([for broken Perl_load_module()], + [c_cv_have_broken_perl_load_module], + AC_LINK_IFELSE( + AC_LANG_PROGRAM( + [[ +#define PERL_NO_GET_CONTEXT +#include +#include +#include + ]], + [[ + dTHX; + load_module (PERL_LOADMOD_NOIMPORT, + newSVpv ("Collectd::Plugin::FooBar", 24), + Nullsv); + ]]), + [c_cv_have_broken_perl_load_module="no"], + [c_cv_have_broken_perl_load_module="yes"] + ) + ) CFLAGS=$SAVE_CFLAGS + LDFLAGS=$SAVE_LDFLAGS fi -AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes") -AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_own_libiptc" = "xyes") -if test "x$with_own_libiptc" = "xyes" +AM_CONDITIONAL(HAVE_BROKEN_PERL_LOAD_MODULE, + test "x$c_cv_have_broken_perl_load_module" = "xyes") + +if test "x$with_libperl" = "xyes" then - AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.]) + SAVE_CFLAGS=$CFLAGS + SAVE_LDFLAGS=$LDFLAGS + CFLAGS="$CFLAGS $PERL_CFLAGS" + LDFLAGS="$LDFLAGS $PERL_LDFLAGS" + + AC_CHECK_MEMBER( + [struct mgvtbl.svt_local], + [have_struct_mgvtbl_svt_local="yes"], + [have_struct_mgvtbl_svt_local="no"], + [ +#include +#include +#include + ]) + + if test "x$have_struct_mgvtbl_svt_local" = "xyes" + then + AC_DEFINE(HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL, 1, + [Define if Perl's struct mgvtbl has member svt_local.]) + fi + + CFLAGS=$SAVE_CFLAGS + LDFLAGS=$SAVE_LDFLAGS fi +# }}} -with_snmp_config="net-snmp-config" -with_snmp_cflags="" -with_snmp_libs="" -AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])], +# --with-libpq {{{ +with_pg_config="pg_config" +with_libpq_includedir="" +with_libpq_libdir="" +with_libpq_cppflags="" +with_libpq_ldflags="" +AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@], + [Path to libpq.])], [ if test "x$withval" = "xno" then - with_libnetsnmp="no" + with_libpq="no" else if test "x$withval" = "xyes" then - with_libnetsnmp="yes" + with_libpq="yes" else - if test -x "$withval" + if test -f "$withval" && test -x "$withval"; then - with_snmp_config="$withval" - with_libnetsnmp="yes" - else - with_snmp_config="$withval/bin/net-snmp-config" - with_libnetsnmp="yes" - fi + with_pg_config="$withval" + else if test -x "$withval/bin/pg_config" + then + with_pg_config="$withval/bin/pg_config" + fi; fi + with_libpq="yes" fi; fi ], -[with_libnetsnmp="yes"]) -if test "x$with_libnetsnmp" = "xyes" +[ + with_libpq="yes" +]) +if test "x$with_libpq" = "xyes" then - with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null` - snmp_config_status=$? + with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null` + pg_config_status=$? - if test $snmp_config_status -ne 0 + if test $pg_config_status -eq 0 then - with_libnetsnmp="no ($with_snmp_config failed)" + if test -n "$with_libpq_includedir"; then + for dir in $with_libpq_includedir; do + with_libpq_cppflags="$with_libpq_cppflags -I$dir" + done + fi else - SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_snmp_cflags" - - AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"]) - - CPPFLAGS="$SAVE_CPPFLAGS" + AC_MSG_WARN([$with_pg_config returned with status $pg_config_status]) fi + + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libpq_cppflags" + + AC_CHECK_HEADERS(libpq-fe.h, [], + [with_libpq="no (libpq-fe.h not found)"], []) + + CPPFLAGS="$SAVE_CPPFLAGS" fi -if test "x$with_libnetsnmp" = "xyes" +if test "x$with_libpq" = "xyes" then - with_snmp_libs=`$with_snmp_config --libs 2>/dev/null` - snmp_config_status=$? + with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null` + pg_config_status=$? - if test $snmp_config_status -ne 0 + if test $pg_config_status -eq 0 then - with_libnetsnmp="no ($with_snmp_config failed)" + if test -n "$with_libpq_libdir"; then + for dir in $with_libpq_libdir; do + with_libpq_ldflags="$with_libpq_ldflags -L$dir" + done + fi else - AC_CHECK_LIB(netsnmp, init_snmp, - [with_libnetsnmp="yes"], - [with_libnetsnmp="no (libnetsnmp not found)"], - [$with_snmp_libs]) + AC_MSG_WARN([$with_pg_config returned with status $pg_config_status]) fi + + SAVE_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $with_libpq_ldflags" + + AC_CHECK_LIB(pq, PQconnectdb, + [with_libpq="yes"], + [with_libpq="no (symbol 'PQconnectdb' not found)"]) + + LDFLAGS="$SAVE_LDFLAGS" fi -if test "x$with_libnetsnmp" = "xyes" +if test "x$with_libpq" = "xyes" then - BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags" - BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs" - AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS) - AC_SUBST(BUILD_WITH_LIBSNMP_LIBS) + BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags" + BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags" + AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS) fi -AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes") - -PKG_CHECK_MODULES([LIBNOTIFY], [libnotify], - [with_libnotify="yes"], - [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"]) +AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes") +# }}} -with_libupsclient_config="" -with_libupsclient_cflags="" -with_libupsclient_libs="" -AC_ARG_WITH(libupsclient, [AS_HELP_STRING([--with-libupsclient@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])], -[ - if test "x$withval" = "xno" - then - with_libupsclient="no" - else if test "x$withval" = "xyes" +# --with-libpthread {{{ +AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])], +[ if test "x$withval" != "xno" \ + && test "x$withval" != "xyes" then - with_libupsclient="use_pkgconfig" + LDFLAGS="$LDFLAGS -L$withval/lib" + CPPFLAGS="$CPPFLAGS -I$withval/include" + with_libpthread="yes" else - if test -x "$withval" - then - with_libupsclient_config="$withval" - with_libupsclient="use_libupsclient_config" - else if test -x "$withval/bin/libupsclient-config" + if test "x$withval" = "xno" then - with_libupsclient_config="$withval/bin/net-snmp-config" - with_libupsclient="use_libupsclient_config" - else - AC_MSG_NOTICE([Not checking for libupsclient: Manually configured]) - with_libupsclient_cflags="-I$withval/include" - with_libupsclient_libs="-L$withval/lib -lupsclient" - with_libupsclient="yes" - fi; fi - fi; fi -], -[with_libupsclient="use_pkgconfig"]) - -# configure using libupsclient-config -if test "x$with_libupsclient" = "xuse_libupsclient_config" -then - AC_MSG_NOTICE([Checking for libupsclient using $with_libupsclient_config]) - with_libupsclient_cflags="`$with_libupsclient_config --cflags`" - if test $? -ne 0 - then - with_libupsclient="no ($with_libupsclient_config failed)" - fi - with_libupsclient_libs="`$with_libupsclient_config --libs`" - if test $? -ne 0 - then - with_libupsclient="no ($with_libupsclient_config failed)" + with_libpthread="no (disabled)" + fi fi -fi -if test "x$with_libupsclient" = "xuse_libupsclient_config" +], [with_libpthread="yes"]) +if test "x$with_libpthread" = "xyes" then - with_libupsclient="yes" + AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], []) fi -# configure using pkg-config -if test "x$with_libupsclient" = "xuse_pkgconfig" +if test "x$with_libpthread" = "xyes" then - if test "x$PKG_CONFIG" = "x" - then - with_libupsclient="no (Don't have pkg-config)" - fi + AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"]) fi -if test "x$with_libupsclient" = "xuse_pkgconfig" +if test "x$with_libpthread" = "xyes" then - AC_MSG_NOTICE([Checking for libupsclient using $PKG_CONFIG]) - $PKG_CONFIG --exists 'libupsclient' 2>/dev/null - if test $? -ne 0 - then - with_libupsclient="no (pkg-config doesn't know library)" - fi + collect_pthread=1 +else + collect_pthread=0 fi -if test "x$with_libupsclient" = "xuse_pkgconfig" -then - with_libupsclient_cflags="`$PKG_CONFIG --cflags 'libupsclient'`" - if test $? -ne 0 - then - with_libupsclient="no ($PKG_CONFIG failed)" - fi - with_libupsclient_libs="`$PKG_CONFIG --libs 'libupsclient'`" - if test $? -ne 0 +AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread], + [Wether or not to use pthread (POSIX threads) library]) +AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes") +# }}} + +# --with-librrd {{{ +# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given]) +librrd_cflags="" +librrd_ldflags="" +librrd_threadsafe="yes" +librrd_rrdc_update="no" +AC_ARG_WITH(librrd, [AS_HELP_STRING([--with-librrd@<:@=PREFIX@:>@], [Path to rrdtool.])], +[ if test "x$withval" != "xno" && test "x$withval" != "xyes" then - with_libupsclient="no ($PKG_CONFIG failed)" + librrd_cflags="-I$withval/include" + librrd_ldflags="-L$withval/lib" + with_librrd="yes" + else + with_librrd="$withval" fi -fi -if test "x$with_libupsclient" = "xuse_pkgconfig" -then - with_libupsclient="yes" -fi - -# with_libupsclient_cflags and with_libupsclient_libs are set up now, let's do -# the actual checks. -if test "x$with_libupsclient" = "xyes" -then - SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" - - AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"]) - - CPPFLAGS="$SAVE_CPPFLAGS" -fi -if test "x$with_libupsclient" = "xyes" +], [with_librrd="yes"]) +if test "x$with_librrd" = "xyes" then SAVE_CPPFLAGS="$CPPFLAGS" SAVE_LDFLAGS="$LDFLAGS" - CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" - LDFLAGS="$LDFLAGS $with_libupsclient_libs" + CPPFLAGS="$CPPFLAGS $librrd_cflags" + LDFLAGS="$LDFLAGS $librrd_ldflags" - AC_CHECK_LIB(upsclient, upscli_connect, - [with_libupsclient="yes"], - [with_libupsclient="no (symbol upscli_connect not found)"]) + AC_CHECK_HEADERS(rrd.h,, [with_librrd="no (rrd.h not found)"]) CPPFLAGS="$SAVE_CPPFLAGS" LDFLAGS="$SAVE_LDFLAGS" fi -if test "x$with_libupsclient" = "xyes" +if test "x$with_librrd" = "xyes" then SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" + SAVE_LDFLAGS="$LDFLAGS" - AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [], -[#include -#include -#include ]) + CPPFLAGS="$CPPFLAGS $librrd_cflags" + LDFLAGS="$LDFLAGS $librrd_ldflags" - CPPFLAGS="$SAVE_CPPFLAGS" -fi -if test "x$with_libupsclient" = "xyes" + AC_CHECK_LIB(rrd_th, rrd_update_r, + [with_librrd="yes" + librrd_ldflags="$librrd_ldflags -lrrd_th -lm" + ], + [librrd_threadsafe="no" + AC_CHECK_LIB(rrd, rrd_update, + [with_librrd="yes" + librrd_ldflags="$librrd_ldflags -lrrd -lm" + ], + [with_librrd="no (symbol 'rrd_update' not found)"], + [-lm]) + ], + [-lm]) + + if test "x$librrd_threadsafe" = "xyes" + then + AC_CHECK_LIB(rrd_th, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"]) + else + AC_CHECK_LIB(rrd, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"]) + fi + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_librrd" = "xyes" then - BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags" - BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs" - AC_SUBST(BUILD_WITH_LIBUPSCLIENT_CFLAGS) - AC_SUBST(BUILD_WITH_LIBUPSCLIENT_LIBS) + BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags" + BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags" + AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS) + AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS) fi +if test "x$librrd_threadsafe" = "xyes" +then + AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).]) +fi +# }}} -### BEGIN of check for libxmms ### -with_xmms_config="xmms-config" -with_xmms_cflags="" -with_xmms_libs="" -AC_ARG_WITH(libxmms, [AS_HELP_STRING([--with-libxmms@<:@=PREFIX@:>@], [Path to libxmms.])], +# --with-libsensors {{{ +with_sensors_cflags="" +with_sensors_ldflags="" +AC_ARG_WITH(libsensors, [AS_HELP_STRING([--with-libsensors@<:@=PREFIX@:>@], [Path to lm_sensors.])], [ - if test "x$withval" != "xno" \ - && test "x$withval" != "xyes" - then - if test -f "$withval" && test -x "$withval"; - then - with_xmms_config="$withval" - else if test -x "$withval/bin/xmms-config" - then - with_xmms_config="$withval/bin/xmms-config" - fi; fi - with_libxmms="yes" - else if test "x$withval" = "xno" + if test "x$withval" = "xno" then - with_libxmms="no" + with_libsensors="no" else - with_libxmms="yes" - fi; fi + with_libsensors="yes" + if test "x$withval" != "xyes" + then + with_sensors_cflags="-I$withval/include" + with_sensors_ldflags="-L$withval/lib" + with_libsensors="yes" + fi + fi ], [ - with_libxmms="yes" -]) -if test "x$with_libxmms" = "xyes" -then - with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null` - xmms_config_status=$? - - if test $xmms_config_status -ne 0 + if test "x$ac_system" = "xLinux" then - with_libxmms="no" + with_libsensors="yes" + else + with_libsensors="no (Linux only library)" fi -fi -if test "x$with_libxmms" = "xyes" +]) +if test "x$with_libsensors" = "xyes" then - with_xmms_libs=`$with_xmms_config --libs 2>/dev/null` - xmms_config_status=$? + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_sensors_cflags" - if test $xmms_config_status -ne 0 - then - with_libxmms="no" - fi +# AC_CHECK_HEADERS(sensors/sensors.h, +# [ +# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the header file.]) +# ], +# [with_libsensors="no (sensors/sensors.h not found)"]) + AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" fi -if test "x$with_libxmms" = "xyes" +if test "x$with_libsensors" = "xyes" then - AC_CHECK_LIB(xmms, xmms_remote_get_info, - [ - BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags" - BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs" - AC_SUBST(BUILD_WITH_LIBXMMS_CFLAGS) - AC_SUBST(BUILD_WITH_LIBXMMS_LIBS) - ], + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS $with_sensors_cflags" + LDFLAGS="$LDFLAGS $with_sensors_ldflags" + + AC_CHECK_LIB(sensors, sensors_init, [ - with_libxmms="no" + AC_DEFINE(HAVE_LIBSENSORS, 1, [Define to 1 if you have the sensors library (-lsensors).]) ], - [$with_xmms_libs]) + [with_libsensors="no (libsensors not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" fi -with_libxmms_numeric=0 -if test "x$with_libxmms" = "xyes" +if test "x$with_libsensors" = "xyes" then - with_libxmms_numeric=1 + BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags" + BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags" + AC_SUBST(BUILD_WITH_LIBSENSORS_CFLAGS) + AC_SUBST(BUILD_WITH_LIBSENSORS_LDFLAGS) fi -AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with_libxmms_numeric], [Define to 1 if you have the 'xmms' library (-lxmms).]) -AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes") -### END of check for libxmms ### +AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_libsensors" = "xyes") +# }}} -with_libnetlink_cflags="" -with_libnetlink_libs="-lnetlink" -AC_ARG_WITH(libnetlink, [AS_HELP_STRING([--with-libnetlink@<:@=PREFIX@:>@], [Path to libnetlink.])], -[ - echo "libnetlink: withval = $withval" - if test "x$withval" = "xyes" - then - with_libnetlink="yes" - else if test "x$withval" = "xno" - then - with_libnetlink="no" - else - if test -d "$withval/include" - then - with_libnetlink_cflags="-I$withval/include" - with_libnetlink_libs="-L$withval/lib -lnetlink" - with_libnetlink="yes" - else - AC_MSG_ERROR("no such directory: $withval/include") - fi - fi; fi -], +# --with-libstatgrab {{{ +with_libstatgrab_cflags="" +with_libstatgrab_ldflags="" +AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])], [ - if test "x$ac_system" = "xLinux" + if test "x$withval" != "xno" \ + && test "x$withval" != "xyes" then - with_libnetlink="yes" + with_libstatgrab_cflags="-I$withval/include" + with_libstatgrab_ldflags="-L$withval/lib -lstatgrab" + with_libstatgrab="yes" + with_libstatgrab_pkg_config="no" else - with_libnetlink="no (Linux only library)" + with_libstatgrab="$withval" + with_libstatgrab_pkg_config="yes" fi + ], +[ + with_libstatgrab="yes" + with_libstatgrab_pkg_config="yes" ]) -if test "x$with_libnetlink" = "xyes" -then - SAVE_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $with_libnetlink_cflags" - - with_libnetlink="no (libnetlink.h not found)" - AC_CHECK_HEADERS(libnetlink.h iproute/libnetlink.h linux/libnetlink.h, - [ - with_libnetlink="yes" - break - ], [], -[#include -#include -#include -#include -#include -#include ]) - AC_CHECK_HEADERS(linux/gen_stats.h linux/pkt_sched.h, [], [], -[#include -#include -#include -#include ]) +if test "x$with_libstatgrab" = "xyes" \ + && test "x$with_libstatgrab_pkg_config" = "xyes" +then + if test "x$PKG_CONFIG" != "x" + then + AC_MSG_CHECKING([pkg-config for libstatgrab]) + temp_result="found" + $PKG_CONFIG --exists libstatgrab 2>/dev/null + if test "$?" != "0" + then + with_libstatgrab_pkg_config="no" + with_libstatgrab="no ($PKG_CONFIG doesn't know libstatgrab)" + temp_result="not found" + fi + AC_MSG_RESULT([$temp_result]) + else + AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.]) + with_libstatgrab_pkg_config="no" + with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab" + fi +fi - AC_COMPILE_IFELSE( -[#include -#include -#include -#include -#include -#include +if test "x$with_libstatgrab" = "xyes" \ + && test "x$with_libstatgrab_pkg_config" = "xyes" \ + && test "x$with_libstatgrab_cflags" = "x" +then + AC_MSG_CHECKING([for libstatgrab CFLAGS]) + temp_result="`$PKG_CONFIG --cflags libstatgrab`" + if test "$?" = "0" + then + with_libstatgrab_cflags="$temp_result" + else + with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)" + temp_result="$PKG_CONFIG --cflags libstatgrab failed" + fi + AC_MSG_RESULT([$temp_result]) +fi -int main (void) -{ - int retval = TCA_STATS2; - return (retval); -}], - [AC_DEFINE([HAVE_TCA_STATS2], 1, [True if the enum-member TCA_STATS2 exists])] - []); +if test "x$with_libstatgrab" = "xyes" \ + && test "x$with_libstatgrab_pkg_config" = "xyes" \ + && test "x$with_libstatgrab_ldflags" = "x" +then + AC_MSG_CHECKING([for libstatgrab LDFLAGS]) + temp_result="`$PKG_CONFIG --libs libstatgrab`" + if test "$?" = "0" + then + with_libstatgrab_ldflags="$temp_result" + else + with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)" + temp_result="$PKG_CONFIG --libs libstatgrab failed" + fi + AC_MSG_RESULT([$temp_result]) +fi - AC_COMPILE_IFELSE( -[#include -#include -#include -#include -#include -#include +if test "x$with_libstatgrab" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags" -int main (void) -{ - int retval = TCA_STATS; - return (retval); -}], - [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])] - []); + AC_CHECK_HEADERS(statgrab.h, + [with_libstatgrab="yes"], + [with_libstatgrab="no (statgrab.h not found)"]) - CFLAGS="$SAVE_CFLAGS" + CPPFLAGS="$SAVE_CPPFLAGS" fi -if test "x$with_libnetlink" = "xyes" + +if test "x$with_libstatgrab" = "xyes" then - AC_CHECK_LIB(netlink, rtnl_open, - [with_libnetlink="yes"], - [with_libnetlink="no (symbol 'rtnl_open' not found)"], - [$with_libnetlink_libs]) + SAVE_CFLAGS="$CFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + + CFLAGS="$CFLAGS $with_libstatgrab_cflags" + LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags" + + AC_CHECK_LIB(statgrab, sg_init, + [with_libstatgrab="yes"], + [with_libstatgrab="no (symbol sg_init not found)"]) + + CFLAGS="$SAVE_CFLAGS" + LDFLAGS="$SAVE_LDFLAGS" fi -if test "x$with_libnetlink" = "xyes" + +AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes") +if test "x$with_libstatgrab" = "xyes" then - BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags" - BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs" - AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS) - AC_SUBST(BUILD_WITH_LIBNETLINK_LIBS) + AC_DEFINE(HAVE_LIBSTATGRAB, 1, [Define to 1 if you have the 'statgrab' library (-lstatgrab)]) + BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags" + BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags" + AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS) + AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS) fi -AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes") +# }}} -with_libopenipmipthread="yes" -with_libopenipmipthread_cflags="" -with_libopenipmipthread_libs="" +# --with-libupsclient {{{ +with_libupsclient_config="" +with_libupsclient_cflags="" +with_libupsclient_libs="" +AC_ARG_WITH(libupsclient, [AS_HELP_STRING([--with-libupsclient@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])], +[ + if test "x$withval" = "xno" + then + with_libupsclient="no" + else if test "x$withval" = "xyes" + then + with_libupsclient="use_pkgconfig" + else + if test -x "$withval" + then + with_libupsclient_config="$withval" + with_libupsclient="use_libupsclient_config" + else if test -x "$withval/bin/libupsclient-config" + then + with_libupsclient_config="$withval/bin/net-snmp-config" + with_libupsclient="use_libupsclient_config" + else + AC_MSG_NOTICE([Not checking for libupsclient: Manually configured]) + with_libupsclient_cflags="-I$withval/include" + with_libupsclient_libs="-L$withval/lib -lupsclient" + with_libupsclient="yes" + fi; fi + fi; fi +], +[with_libupsclient="use_pkgconfig"]) -AC_MSG_CHECKING([for pkg-config]) -temp_result="no" -if test "x$PKG_CONFIG" = "x" +# configure using libupsclient-config +if test "x$with_libupsclient" = "xuse_libupsclient_config" then - with_libopenipmipthread="no" - temp_result="no" -else - temp_result="$PKG_CONFIG" + AC_MSG_NOTICE([Checking for libupsclient using $with_libupsclient_config]) + with_libupsclient_cflags="`$with_libupsclient_config --cflags`" + if test $? -ne 0 + then + with_libupsclient="no ($with_libupsclient_config failed)" + fi + with_libupsclient_libs="`$with_libupsclient_config --libs`" + if test $? -ne 0 + then + with_libupsclient="no ($with_libupsclient_config failed)" + fi +fi +if test "x$with_libupsclient" = "xuse_libupsclient_config" +then + with_libupsclient="yes" fi -AC_MSG_RESULT([$temp_result]) -if test "x$with_libopenipmipthread" = "xyes" +# configure using pkg-config +if test "x$with_libupsclient" = "xuse_pkgconfig" then - AC_MSG_CHECKING([for libOpenIPMIpthread]) - $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null - if test "$?" != "0" + if test "x$PKG_CONFIG" = "x" then - with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)" + with_libupsclient="no (Don't have pkg-config)" fi - AC_MSG_RESULT([$with_libopenipmipthread]) fi - -if test "x$with_libopenipmipthread" = "xyes" +if test "x$with_libupsclient" = "xuse_pkgconfig" then - AC_MSG_CHECKING([for libOpenIPMIpthread CFLAGS]) - temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`" - if test "$?" = "0" + AC_MSG_NOTICE([Checking for libupsclient using $PKG_CONFIG]) + $PKG_CONFIG --exists 'libupsclient' 2>/dev/null + if test $? -ne 0 then - with_libopenipmipthread_cflags="$temp_result" - else - with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)" - temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed" + with_libupsclient="no (pkg-config doesn't know library)" fi - AC_MSG_RESULT([$temp_result]) fi - -if test "x$with_libopenipmipthread" = "xyes" +if test "x$with_libupsclient" = "xuse_pkgconfig" then - AC_MSG_CHECKING([for libOpenIPMIpthread LDFLAGS]) - temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`" - if test "$?" = "0" + with_libupsclient_cflags="`$PKG_CONFIG --cflags 'libupsclient'`" + if test $? -ne 0 then - with_libopenipmipthread_ldflags="$temp_result" - else - with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)" - temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed" + with_libupsclient="no ($PKG_CONFIG failed)" fi - AC_MSG_RESULT([$temp_result]) + with_libupsclient_libs="`$PKG_CONFIG --libs 'libupsclient'`" + if test $? -ne 0 + then + with_libupsclient="no ($PKG_CONFIG failed)" + fi +fi +if test "x$with_libupsclient" = "xuse_pkgconfig" +then + with_libupsclient="yes" +fi + +# with_libupsclient_cflags and with_libupsclient_libs are set up now, let's do +# the actual checks. +if test "x$with_libupsclient" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" + + AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" fi - -if test "x$with_libopenipmipthread" = "xyes" +if test "x$with_libupsclient" = "xyes" then SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags" + SAVE_LDFLAGS="$LDFLAGS" - AC_CHECK_HEADERS(OpenIPMI/ipmi_smi.h, - [with_libopenipmipthread="yes"], - [with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"], -[#include -#include -#include -#include -]) + CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" + LDFLAGS="$LDFLAGS $with_libupsclient_libs" + + AC_CHECK_LIB(upsclient, upscli_connect, + [with_libupsclient="yes"], + [with_libupsclient="no (symbol upscli_connect not found)"]) CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" fi +if test "x$with_libupsclient" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags" -if test "x$with_libopenipmipthread" = "xyes" + AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [], +[#include +#include +#include ]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libupsclient" = "xyes" then - BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags" - BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags" - AC_SUBST(BUILD_WITH_OPENIPMI_CFLAGS) - AC_SUBST(BUILD_WITH_OPENIPMI_LIBS) + BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags" + BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs" + AC_SUBST(BUILD_WITH_LIBUPSCLIENT_CFLAGS) + AC_SUBST(BUILD_WITH_LIBUPSCLIENT_LIBS) fi +# }}} -dnl Check for libpq. -with_pg_config="pg_config" -with_libpq_includedir="" -with_libpq_libdir="" -with_libpq_cppflags="" -with_libpq_ldflags="" -AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@], - [Path to libpq.])], +# --with-libxmms {{{ +with_xmms_config="xmms-config" +with_xmms_cflags="" +with_xmms_libs="" +AC_ARG_WITH(libxmms, [AS_HELP_STRING([--with-libxmms@<:@=PREFIX@:>@], [Path to libxmms.])], [ - if test "x$withval" = "xno" - then - with_libpq="no" - else if test "x$withval" = "xyes" + if test "x$withval" != "xno" \ + && test "x$withval" != "xyes" then - with_libpq="yes" - else if test -f "$withval" && test -x "$withval"; then - with_pg_config="$withval" - else if test -x "$withval/bin/pg_config" + with_xmms_config="$withval" + else if test -x "$withval/bin/xmms-config" then - with_pg_config="$withval/bin/pg_config" + with_xmms_config="$withval/bin/xmms-config" fi; fi - with_libpq="yes" + with_libxmms="yes" + else if test "x$withval" = "xno" + then + with_libxmms="no" + else + with_libxmms="yes" fi; fi ], [ - with_libpq="yes" + with_libxmms="yes" ]) -if test "x$with_libpq" = "xyes" +if test "x$with_libxmms" = "xyes" then - with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null` - pg_config_status=$? + with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null` + xmms_config_status=$? - if test $pg_config_status -eq 0 + if test $xmms_config_status -ne 0 then - if test -n "$with_libpq_includedir"; then - for dir in $with_libpq_includedir; do - with_libpq_cppflags="$with_libpq_cppflags -I$dir" - done - fi - else - AC_MSG_WARN([$with_pg_config returned with status $pg_config_status]) + with_libxmms="no" fi - - SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $with_libpq_cppflags" - - AC_CHECK_HEADERS(libpq-fe.h, [], - [with_libpq="no (libpq-fe.h not found)"], []) - - CPPFLAGS="$SAVE_CPPFLAGS" fi -if test "x$with_libpq" = "xyes" +if test "x$with_libxmms" = "xyes" then - with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null` - pg_config_status=$? + with_xmms_libs=`$with_xmms_config --libs 2>/dev/null` + xmms_config_status=$? - if test $pg_config_status -eq 0 + if test $xmms_config_status -ne 0 then - if test -n "$with_libpq_libdir"; then - for dir in $with_libpq_libdir; do - with_libpq_ldflags="$with_libpq_ldflags -L$dir" - done - fi - else - AC_MSG_WARN([$with_pg_config returned with status $pg_config_status]) + with_libxmms="no" fi - - SAVE_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $with_libpq_ldflags" - - AC_CHECK_LIB(pq, PQconnectdb, - [with_libpq="yes"], - [with_libpq="no (symbol 'PQconnectdb' not found)"]) - - LDFLAGS="$SAVE_LDFLAGS" fi -if test "x$with_libpq" = "xyes" +if test "x$with_libxmms" = "xyes" then - BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags" - BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags" - AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS) - AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS) + AC_CHECK_LIB(xmms, xmms_remote_get_info, + [ + BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags" + BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs" + AC_SUBST(BUILD_WITH_LIBXMMS_CFLAGS) + AC_SUBST(BUILD_WITH_LIBXMMS_LIBS) + ], + [ + with_libxmms="no" + ], + [$with_xmms_libs]) fi -AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes") +with_libxmms_numeric=0 +if test "x$with_libxmms" = "xyes" +then + with_libxmms_numeric=1 +fi +AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with_libxmms_numeric], [Define to 1 if you have the 'xmms' library (-lxmms).]) +AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes") +# }}} -dnl Check for libvirt and libxml2 libraries. +# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{ with_libxml2="no (pkg-config isn't available)" with_libxml2_cflags="" with_libxml2_ldflags="" @@ -2523,8 +2684,92 @@ if test "x$with_libvirt" = "xyes"; then AC_SUBST(BUILD_WITH_LIBVIRT_CFLAGS) AC_SUBST(BUILD_WITH_LIBVIRT_LIBS) fi +# }}} + +# $PKG_CONFIG --exists OpenIPMIpthread {{{ +with_libopenipmipthread="yes" +with_libopenipmipthread_cflags="" +with_libopenipmipthread_libs="" + +AC_MSG_CHECKING([for pkg-config]) +temp_result="no" +if test "x$PKG_CONFIG" = "x" +then + with_libopenipmipthread="no" + temp_result="no" +else + temp_result="$PKG_CONFIG" +fi +AC_MSG_RESULT([$temp_result]) + +if test "x$with_libopenipmipthread" = "xyes" +then + AC_MSG_CHECKING([for libOpenIPMIpthread]) + $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null + if test "$?" != "0" + then + with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)" + fi + AC_MSG_RESULT([$with_libopenipmipthread]) +fi + +if test "x$with_libopenipmipthread" = "xyes" +then + AC_MSG_CHECKING([for libOpenIPMIpthread CFLAGS]) + temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`" + if test "$?" = "0" + then + with_libopenipmipthread_cflags="$temp_result" + else + with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)" + temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed" + fi + AC_MSG_RESULT([$temp_result]) +fi + +if test "x$with_libopenipmipthread" = "xyes" +then + AC_MSG_CHECKING([for libOpenIPMIpthread LDFLAGS]) + temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`" + if test "$?" = "0" + then + with_libopenipmipthread_ldflags="$temp_result" + else + with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)" + temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed" + fi + AC_MSG_RESULT([$temp_result]) +fi + +if test "x$with_libopenipmipthread" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags" + + AC_CHECK_HEADERS(OpenIPMI/ipmi_smi.h, + [with_libopenipmipthread="yes"], + [with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"], +[#include +#include +#include +#include +]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi + +if test "x$with_libopenipmipthread" = "xyes" +then + BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags" + BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags" + AC_SUBST(BUILD_WITH_OPENIPMI_CFLAGS) + AC_SUBST(BUILD_WITH_OPENIPMI_LIBS) +fi +# }}} -dnl End of check for libvirt and libxml2 libraries. +PKG_CHECK_MODULES([LIBNOTIFY], [libnotify], + [with_libnotify="yes"], + [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"]) # Check for enabled/disabled features # @@ -2638,6 +2883,7 @@ AC_COLLECTD([getifaddrs],[enable], [feature], [getifaddrs under Linux]) dependency_error="no" plugin_ascent="no" plugin_battery="no" +plugin_bind="no" plugin_cpu="no" plugin_cpufreq="no" plugin_df="no" @@ -2734,6 +2980,7 @@ fi if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes" then plugin_ascent="yes" + plugin_bind="yes" fi if test "x$with_libopenipmipthread" = "xyes" @@ -2745,6 +2992,11 @@ if test "x$have_processor_info" = "xyes" then plugin_cpu="yes" fi +if test "x$have_sysctl" = "xyes" +then + plugin_cpu="yes" + plugin_swap="yes" +fi if test "x$have_sysctlbyname" = "xyes" then plugin_cpu="yes" @@ -2833,6 +3085,11 @@ then plugin_swap="yes" fi +if test "x$have_swapctl" = "xyes" +then + plugin_swap="yes" +fi + if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes" then plugin_tcpconns="yes" @@ -2847,8 +3104,6 @@ then plugin_users="yes" fi -# FIXME: sysctl for swap plugin - m4_divert_once([HELP_ENABLE], [ collectd plugins:]) @@ -2857,10 +3112,12 @@ AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC]) AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple's hardware sensors]) AC_PLUGIN([ascent], [$plugin_ascent], [AscentEmu player statistics]) AC_PLUGIN([battery], [$plugin_battery], [Battery statistics]) -AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics]) +AC_PLUGIN([bind], [$plugin_bind], [ISC Bind nameserver statistics]) AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics]) +AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics]) AC_PLUGIN([csv], [yes], [CSV output plugin]) -AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications]) +AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics]) +AC_PLUGIN([dbi], [$with_libdbi], [General database statistics]) AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics]) AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics]) AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis]) @@ -2870,13 +3127,16 @@ AC_PLUGIN([exec], [yes], [Execution of external programs]) AC_PLUGIN([filecount], [yes], [Count files in directories]) AC_PLUGIN([hddtemp], [yes], [Query hddtempd]) AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics]) -AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters]) AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics]) +AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters]) AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics]) AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics]) AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics]) AC_PLUGIN([load], [$plugin_load], [System load]) AC_PLUGIN([logfile], [yes], [File logging plugin]) +AC_PLUGIN([match_regex], [yes], [The regex match]) +AC_PLUGIN([match_timediff], [yes], [The timediff match]) +AC_PLUGIN([match_value], [yes], [The value match]) AC_PLUGIN([mbmon], [yes], [Query mbmond]) AC_PLUGIN([memcached], [yes], [memcached statistics]) AC_PLUGIN([memory], [$plugin_memory], [Memory usage]) @@ -2886,23 +3146,30 @@ AC_PLUGIN([netlink], [$with_libnetlink], [Enhanced Linux network statistic AC_PLUGIN([network], [yes], [Network communication plugin]) AC_PLUGIN([nfs], [$plugin_nfs], [NFS statistics]) AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics]) +AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications]) AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier]) AC_PLUGIN([ntpd], [yes], [NTPd statistics]) AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics]) AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics]) +AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics]) +AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin]) AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter]) AC_PLUGIN([ping], [$with_liboping], [Network latency statistics]) AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database statistics]) AC_PLUGIN([powerdns], [yes], [PowerDNS statistics]) AC_PLUGIN([processes], [$plugin_processes], [Process statistics]) -AC_PLUGIN([rrdtool], [$with_rrdtool], [RRDTool output plugin]) -AC_PLUGIN([sensors], [$with_lm_sensors], [lm_sensors statistics]) +AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin]) +AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin]) +AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics]) AC_PLUGIN([serial], [$plugin_serial], [serial port traffic]) AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin]) AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics]) AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin]) AC_PLUGIN([tail], [yes], [Parsing of logfiles]) AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics]) +AC_PLUGIN([target_notification], [yes], [The notification target]) +AC_PLUGIN([target_replace], [yes], [The replace target]) +AC_PLUGIN([target_set], [yes], [The set target]) AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics]) AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics]) AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics]) @@ -2951,12 +3218,29 @@ fi AC_SUBST(PERL_BINDINGS) AC_SUBST(PERL_BINDINGS_OPTIONS) -AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/liboconfig/Makefile src/liboping/Makefile bindings/Makefile) +dnl libcollectdclient +LCC_VERSION_MAJOR=`echo $PACKAGE_VERSION | cut -d'.' -f1` +LCC_VERSION_MINOR=`echo $PACKAGE_VERSION | cut -d'.' -f2` +LCC_VERSION_PATCH=`echo $PACKAGE_VERSION | cut -d'.' -f3` + +LCC_VERSION_EXTRA=`echo $PACKAGE_VERSION | cut -d'.' -f4-` + +LCC_VERSION_STRING="$LCC_VERSION_MAJOR.$LCC_VERSION_MINOR.$LCC_VERSION_PATCH" -if test "x$with_rrdtool" = "xyes" \ +AC_SUBST(LCC_VERSION_MAJOR) +AC_SUBST(LCC_VERSION_MINOR) +AC_SUBST(LCC_VERSION_PATCH) +AC_SUBST(LCC_VERSION_EXTRA) +AC_SUBST(LCC_VERSION_STRING) + +AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h) + +AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile src/liboping/Makefile bindings/Makefile) + +if test "x$with_librrd" = "xyes" \ && test "x$librrd_threadsafe" != "xyes" then - with_rrdtool="yes (warning: librrd is not thread-safe)" + with_librrd="yes (warning: librrd is not thread-safe)" fi if test "x$with_liboping" = "xyes" \ @@ -2988,6 +3272,7 @@ cat < plugin above provides C and C which are both voltages, you can use a hyphen to add a "type instance" to the type. For a list of already defined "types" look at the F file in -collectd's library path, e.Eg. F. +collectd's shared data directory, e.Eg. F. =item B I diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec index 89ce1237..35eb8bec 100644 --- a/contrib/fedora/collectd.spec +++ b/contrib/fedora/collectd.spec @@ -232,7 +232,7 @@ exit 0 %attr(0644,root,root) %{_libdir}/%{name}/wireless.so* %attr(0644,root,root) %{_libdir}/%{name}/wireless.la -%attr(0644,root,root) %{_libdir}/%{name}/types.db +%attr(0644,root,root) %{_datadir}/%{name}/types.db %dir /var/lib/collectd diff --git a/contrib/oracle/create_schema.ddl b/contrib/oracle/create_schema.ddl new file mode 100644 index 00000000..86b1e83e --- /dev/null +++ b/contrib/oracle/create_schema.ddl @@ -0,0 +1,264 @@ +-- collectd - contrib/oracle/create_schema.ddl +-- Copyright (C) 2008,2009 Roman Klesel +-- +-- 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; only version 2 of the License is applicable. +-- +-- 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., +-- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-- +-- Authors: +-- Roman Klesel + +-- Description +-------------- +-- This will create a schema to provide collectd with the required permissions +-- and space for statistic data. +-- The idea is to store the output of some expensive queries in static tables +-- and fill these tables with dbms_scheduler jobs as often as necessary. +-- collectd will then just read from the static tables. This will reduces the +-- chance that your system will be killed by excessive monitoring queries and +-- gives the dba control on the interval the information provided to collectd +-- will be refreshed. You have to create a dbms_scheduler job for each of the +-- schemas you what to monitor for object-space-usage. See the example below. +-- +-- Requirements +--------------- +-- make sure you have: +-- write permission in $PWD +-- you have GID of oracle software owner +-- set $ORACLE_HOME +-- set $ORACLE_SID +-- DB is up an running in RW mode +-- execute like this: +-- sqlplus /nolog @ create_collectd-schema.dll + +spool create_collectd-schema.log +connect / as sysdba + +-- Create user, tablespace and permissions + +CREATE TABLESPACE "COLLECTD-TBS" + DATAFILE SIZE 30M + AUTOEXTEND ON + NEXT 10M + MAXSIZE 300M + LOGGING + EXTENT MANAGEMENT LOCAL + SEGMENT SPACE MANAGEMENT AUTO + DEFAULT NOCOMPRESS; + +CREATE ROLE "CREATE_COLLECTD_SCHEMA" NOT IDENTIFIED; +GRANT CREATE JOB TO "CREATE_COLLECTD_SCHEMA"; +GRANT CREATE SEQUENCE TO "CREATE_COLLECTD_SCHEMA"; +GRANT CREATE SYNONYM TO "CREATE_COLLECTD_SCHEMA"; +GRANT CREATE TABLE TO "CREATE_COLLECTD_SCHEMA"; +GRANT CREATE VIEW TO "CREATE_COLLECTD_SCHEMA"; +GRANT CREATE PROCEDURE TO "CREATE_COLLECTD_SCHEMA"; + +CREATE USER "COLLECTDU" + PROFILE "DEFAULT" + IDENTIFIED BY "Change_me-1st" + PASSWORD EXPIRE + DEFAULT TABLESPACE "COLLECTD-TBS" + TEMPORARY TABLESPACE "TEMP" + QUOTA UNLIMITED ON "COLLECTD-TBS" + ACCOUNT UNLOCK; + +GRANT "CONNECT" TO "COLLECTDU"; +GRANT "SELECT_CATALOG_ROLE" TO "COLLECTDU"; +GRANT "CREATE_COLLECTD_SCHEMA" TO "COLLECTDU"; +GRANT analyze any TO "COLLECTDU"; +GRANT select on dba_tables TO "COLLECTDU"; +GRANT select on dba_lobs TO "COLLECTDU"; +GRANT select on dba_indexes TO "COLLECTDU"; +GRANT select on dba_segments TO "COLLECTDU"; +GRANT select on dba_tab_columns TO "COLLECTDU"; +GRANT select on dba_free_space TO "COLLECTDU"; +GRANT select on dba_data_files TO "COLLECTDU"; +-- Create tables and indexes + +alter session set current_schema=collectdu; + +create table c_tbs_usage ( + tablespace_name varchar2(30), + bytes_free number, + bytes_used number, + CONSTRAINT "C_TBS_USAGE_UK1" UNIQUE ("TABLESPACE_NAME") USING INDEX + TABLESPACE "COLLECTD-TBS" ENABLE) + TABLESPACE "COLLECTD-TBS"; + +CREATE TABLE "COLLECTDU"."C_TBL_SIZE" ( + "OWNER" VARCHAR2(30 BYTE), + "TABLE_NAME" VARCHAR2(30 BYTE), + "BYTES" NUMBER, + CONSTRAINT "C_TBL_SIZE_UK1" UNIQUE ("OWNER", "TABLE_NAME") + USING INDEX TABLESPACE "COLLECTD-TBS" ENABLE) + TABLESPACE "COLLECTD-TBS" ; + + +create or replace PROCEDURE get_object_size(owner IN VARCHAR2) AS + +v_owner VARCHAR2(30) := owner; + +l_free_blks NUMBER; +l_total_blocks NUMBER; +l_total_bytes NUMBER; +l_unused_blocks NUMBER; +l_unused_bytes NUMBER; +l_lastusedextfileid NUMBER; +l_lastusedextblockid NUMBER; +l_last_used_block NUMBER; + +CURSOR cur_tbl IS +SELECT owner, + TABLE_NAME +FROM dba_tables +WHERE owner = v_owner; + +CURSOR cur_idx IS +SELECT owner, + index_name, + TABLE_NAME +FROM dba_indexes +WHERE owner = v_owner; + +CURSOR cur_lob IS +SELECT owner, + segment_name, + TABLE_NAME +FROM dba_lobs +WHERE owner = v_owner; + +BEGIN + + DELETE FROM c_tbl_size + WHERE owner = v_owner; + COMMIT; + + FOR r_tbl IN cur_tbl + LOOP + BEGIN + dbms_space.unused_space(segment_owner => r_tbl.owner, segment_name => r_tbl.TABLE_NAME, segment_type => 'TABLE', total_blocks => l_total_blocks, total_bytes => l_total_bytes, unused_blocks => l_unused_blocks, unused_bytes => l_unused_bytes, last_used_extent_file_id => l_lastusedextfileid, last_used_extent_block_id => l_lastusedextblockid, last_used_block => l_last_used_block); + + EXCEPTION + WHEN others THEN + DBMS_OUTPUT.PUT_LINE('tbl_name: ' || r_tbl.TABLE_NAME); + END; + INSERT + INTO c_tbl_size + VALUES(r_tbl.owner, r_tbl.TABLE_NAME, l_total_bytes -l_unused_bytes); + END LOOP; + + COMMIT; + + FOR r_idx IN cur_idx + LOOP + BEGIN + dbms_space.unused_space(segment_owner => r_idx.owner, segment_name => r_idx.index_name, segment_type => 'INDEX', total_blocks => l_total_blocks, total_bytes => l_total_bytes, unused_blocks => l_unused_blocks, unused_bytes => l_unused_bytes, last_used_extent_file_id => l_lastusedextfileid, last_used_extent_block_id => l_lastusedextblockid, last_used_block => l_last_used_block); + + EXCEPTION + WHEN others THEN + DBMS_OUTPUT.PUT_LINE('idx_name: ' || r_idx.index_name); + END; + + UPDATE c_tbl_size + SET bytes = bytes + l_total_bytes -l_unused_bytes + WHERE owner = r_idx.owner + AND TABLE_NAME = r_idx.TABLE_NAME; + END LOOP; + + COMMIT; + + FOR r_lob IN cur_lob + LOOP + BEGIN + dbms_space.unused_space(segment_owner => r_lob.owner, segment_name => r_lob.segment_name, segment_type => 'LOB', total_blocks => l_total_blocks, total_bytes => l_total_bytes, unused_blocks => l_unused_blocks, unused_bytes => l_unused_bytes, last_used_extent_file_id => l_lastusedextfileid, last_used_extent_block_id => l_lastusedextblockid, last_used_block => l_last_used_block); + + EXCEPTION + WHEN others THEN + DBMS_OUTPUT.PUT_LINE('lob_name: ' || r_lob.segment_name); + END; + + UPDATE c_tbl_size + SET bytes = bytes + l_total_bytes -l_unused_bytes + WHERE owner = r_lob.owner + AND TABLE_NAME = r_lob.TABLE_NAME; + END LOOP; + + COMMIT; + +END get_object_size; +/ + +create or replace PROCEDURE get_tbs_size AS +BEGIN + +execute immediate 'truncate table c_tbs_usage'; + +insert into c_tbs_usage ( +select df.tablespace_name as tablespace_name, + decode(df.maxbytes, + 0, + sum(fs.bytes), + (df.maxbytes-(df.bytes-sum(fs.bytes)))) as bytes_free, + decode(df.maxbytes, + 0, + round((df.bytes-sum(fs.bytes))), + round(df.maxbytes-(df.maxbytes-(df.bytes-sum(fs.bytes))))) as bytes_used +from dba_free_space fs inner join + (select + tablespace_name, + sum(bytes) bytes, + sum(decode(maxbytes,0,bytes,maxbytes)) maxbytes + from dba_data_files + group by tablespace_name ) df +on fs.tablespace_name = df.tablespace_name +group by df.tablespace_name,df.maxbytes,df.bytes); + +COMMIT; + +END get_tbs_size; +/ + +BEGIN +sys.dbms_scheduler.create_job( +job_name => '"COLLECTDU"."C_TBSSIZE_JOB"', +job_type => 'PLSQL_BLOCK', +job_action => 'begin + get_tbs_size(); +end;', +repeat_interval => 'FREQ=MINUTELY;INTERVAL=5', +start_date => systimestamp at time zone 'Europe/Berlin', +job_class => '"DEFAULT_JOB_CLASS"', +auto_drop => FALSE, +enabled => TRUE); +END; +/ + +BEGIN +sys.dbms_scheduler.create_job( +job_name => '"COLLECTDU"."C_TBLSIZE_COLLECTDU_JOB"', +job_type => 'PLSQL_BLOCK', +job_action => 'begin + get_object_size( owner => ''COLLECTDU'' ); +end;', +repeat_interval => 'FREQ=HOURLY;INTERVAL=12', +start_date => systimestamp at time zone 'Europe/Berlin', +job_class => '"DEFAULT_JOB_CLASS"', +auto_drop => FALSE, +enabled => TRUE); +END; +/ + +spool off +quit + +-- vim: set syntax=sql : diff --git a/contrib/oracle/db_systat.sql b/contrib/oracle/db_systat.sql new file mode 100644 index 00000000..cf2a3c4a --- /dev/null +++ b/contrib/oracle/db_systat.sql @@ -0,0 +1,55 @@ +-- Table sizes +SELECT owner, + TABLE_NAME, + bytes +FROM collectdu.c_tbl_size; + +-- Tablespace sizes +SELECT tablespace_name, + bytes_free, + bytes_used +FROM collectdu.c_tbs_usage; + +-- IO per Tablespace +SELECT SUM(vf.phyblkrd) *8192 AS +phy_blk_r, + SUM(vf.phyblkwrt) *8192 AS +phy_blk_w, + 'tablespace' AS +i_prefix, + dt.tablespace_name +FROM((dba_data_files dd JOIN v$filestat vf ON dd.file_id = vf.file#) JOIN dba_tablespaces dt ON dd.tablespace_name = dt.tablespace_name) +GROUP BY dt.tablespace_name; + +-- Buffer Pool Hit Ratio: +SELECT DISTINCT 100 *ROUND(1 -((MAX(decode(name, 'physical reads cache', VALUE))) /(MAX(decode(name, 'db block gets from cache', VALUE)) + MAX(decode(name, 'consistent gets from cache', VALUE)))), 4) AS +VALUE, + 'BUFFER_CACHE_HIT_RATIO' AS +buffer_cache_hit_ratio +FROM v$sysstat; + +-- Shared Pool Hit Ratio: +SELECT + 100.0 * sum(PINHITS) / sum(pins) as VALUE, + 'SHAREDPOOL_HIT_RATIO' AS SHAREDPOOL_HIT_RATIO +FROM V$LIBRARYCACHE; + +-- PGA Hit Ratio: +SELECT VALUE, + 'PGA_HIT_RATIO' AS +pga_hit_ratio +FROM v$pgastat +WHERE name = 'cache hit percentage'; + +-- DB Efficiency +SELECT ROUND(SUM(decode(metric_name, 'Database Wait Time Ratio', VALUE)), 2) AS +database_wait_time_ratio, + ROUND(SUM(decode(metric_name, 'Database CPU Time Ratio', VALUE)), 2) AS +database_cpu_time_ratio, + 'DB_EFFICIENCY' AS +db_efficiency +FROM sys.v_$sysmetric +WHERE metric_name IN('Database CPU Time Ratio', 'Database Wait Time Ratio') + AND intsize_csec = + (SELECT MAX(intsize_csec) + FROM sys.v_$sysmetric); diff --git a/contrib/redhat/collectd.conf b/contrib/redhat/collectd.conf index 7a026fac..0aaaee31 100644 --- a/contrib/redhat/collectd.conf +++ b/contrib/redhat/collectd.conf @@ -9,7 +9,7 @@ FQDNLookup true BaseDir "/var/lib/collectd" PIDFile "/var/run/collectd.pid" PluginDir "/usr/lib/collectd" -TypesDB "/usr/lib/collectd/types.db" +TypesDB "/usr/share/collectd/types.db" Interval 10 ReadThreads 5 diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index bce76473..62acc184 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -85,7 +85,7 @@ cp contrib/redhat/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf sed -i 's:#BaseDir "/usr/var/lib/collectd":BaseDir "/var/lib/collectd":' $RPM_BUILD_ROOT/etc/collectd.conf sed -i 's:#PIDFile "/usr/var/run/collectd.pid":PIDFile "/var/run/collectd.pid":' $RPM_BUILD_ROOT/etc/collectd.conf sed -i 's:#PluginDir "/usr/lib/collectd":PluginDir "/usr/lib/collectd":' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#TypesDB "/usr/lib/collectd/types.db":TypesDB "/usr/lib/collectd/types.db":' $RPM_BUILD_ROOT/etc/collectd.conf +sed -i 's:#TypesDB "/usr/share/collectd/types.db":TypesDB "/usr/share/collectd/types.db":' $RPM_BUILD_ROOT/etc/collectd.conf sed -i 's:#Interval 10:Interval 10:' $RPM_BUILD_ROOT/etc/collectd.conf sed -i 's:#ReadThreads 5:ReadThreads 5:' $RPM_BUILD_ROOT/etc/collectd.conf ##Move config contribs @@ -247,7 +247,7 @@ exit 0 %attr(0644,root,root) %{_libdir}/%{name}/wireless.so* %attr(0644,root,root) %{_libdir}/%{name}/wireless.la -%attr(0644,root,root) %{_libdir}/%{name}/types.db +%attr(0644,root,root) %{_datadir}/%{name}/types.db %exclude %{_libdir}/perl5/5.8.8/%{_arch}-linux-thread-multi/perllocal.pod %attr(0644,root,root) %{_libdir}/perl5/site_perl/5.8.8/Collectd.pm diff --git a/contrib/solaris-smf/README b/contrib/solaris-smf/README new file mode 100644 index 00000000..dfd990b2 --- /dev/null +++ b/contrib/solaris-smf/README @@ -0,0 +1,331 @@ +SMF is the way Solaris 10 and later preferably manages services. It is intended +to replace the old init.d process and provides advances features, such as +automatic restarting of failing services. + +The following blog entry by Piotr Hosowicz describes the process in more +detail. The original entry can be found at +. + +The files in this directory are: + + README This file + collectd Start / stop script + collectd.xml SMF manifest for collectd. + +------------------------------------------------------------------------ + + SMF-izing collectd <#> + +Wpis na 0. poziomie, wysłany 21 grudnia 2008 o 16:30:49. + +My two previous blog entries were about building and running collectd + on Sun Solaris 10. After the first one Octo +contacted me and was so kind as to release a packaged version for x86_64 +. I have put aside the build +I rolled on my own and decided to install and run the packaged one on +the production servers. This blog entry is about SMF-izing the collectd +daemon. + +A few words about the SMF – the Solaris'es Service Management Facility. +I think it appeared in Solaris 10. From then on the good old |/etc/rcN.d +|| /etc/init.d| services are called /legacy services/. They still can be +run, but are not fully supported by SMF. SMF enables you to start and +stop services in the unified way, can direct you to man pages in case a +service enters maintenance mode, resolves dependencies between services, +can store properties of services and so on. A nice feature is that SMF +will take care of restarting services in case they terminate +unexpectedly, we will use it at the end to check that things are working +as they should. + +The 3V|L thing about SMF is that each service needs so called SMF +manifest written in XML and a script or scripts that are executed, when +the service needs to be stopped or started. It can be one script, which +should accept respective parameters. Even more 3V|L is the fact that the +manifest is imported into the SMF database and kept there in SQLite format. + +Below you will find collectd manifest and the script. I will post them +to collectd mailing list in matter of minutes with this blog entry +serving as a README. Please read all down to the bottom, including the +remarks. + +Manifest (based on the work of Kangurek, thanks!), see the "collectd.xml" +file: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Script, see the "collectd" file: + + +#!/sbin/sh + +PIDFILE=/opt/collectd/var/run/collectd.pid +DAEMON=/opt/collectd/sbin/collectd + +. /lib/svc/share/smf_include.sh + +case "$1" in + start) + if [ -f $PIDFILE ] ; then + echo "Already running. Stale PID file?" + PID=`cat $PIDFILE` + echo "$PIDFILE contains $PID" + ps -p $PID + exit $SMF_EXIT_ERR_FATAL + fi + $DAEMON + if [ $? -ne 0 ] ; then + echo $DAEMON faild to start + exit $SMF_EXIT_ERR_FATAL + fi + ;; + stop) + PID=`cat $PIDFILE 2>/dev/null` + kill -15 $PID 2>/dev/null + pwait $PID 1> /dev/null 2>/dev/null + ;; + restart) + $0 stop + $0 start + ;; + status) + ps -ef | grep collectd | grep -v status | grep -v grep + ;; + *) + echo "Usage: $0 [ start | stop | restart | status ]" + exit 1 + ;; +esac + + +exit $SMF_EXIT_OK + + + +So you have two files: |collectd| script and |collectd.xml| manifest. +What do you do with these files? + +First – before you begin – make sure that collectd is not running, close +it down. My script above assumes that you are using the default place +for PID file. Second: remove / move away collectd's |/etc/rcN.d| and +|/etc/init.d| stuff, you won't need it from now on, because collectd +will be SMF-ized. Tada! + +Next – install the script in place. It took me a minute or two to figure +out why Solaris'es |install| tool does not work as expected. It turned +out that the switches and parameters must be in exactly same order as in +man page, especially the -c parameter must be first: + +|# install -c /lib/svc/method/ -m 755 -u root -g bin collectd| + +Now is the moment to test once again that the script is working OK. Try +running: + +|# /lib/svc/method/collectd start +# /lib/svc/method/collectd stop +# /lib/svc/method/collectd restart +| + +|pgrep| and |kill| are your friends here, also collectd logs. At last +stop the collectd service and continue. + +Now is the time to /slurp/ attached XML manifest into the SMF database. +This is done using the |svccfg| tool. Transcript follows: + +|# svccfg +svc:> validate collectd.xml +svc:> import collectd.xml +svc:> +| + +It is good to run |validate| command first, especially if you copied and +pasted the XML manifest from this HTML document opened in your +browser!!! Second thing worth noting is that |svccfg| starts the service +immediately upon importing the manifest. It might be not what you want. +For example it will start collecting data on remote collectd server if +you use network plugin and it will do it under the hostname, that is not +right. So be sure to configure collectd prior to running it from SMF. + +Now a few words about SMF tools. To see the state of all services issue +|svcs -a| command. To see state of collectd service issue |svcs +collectd| command. Quite normal states are enabled and disabled. If you +see maintenance state then something is wrong. Be sure that you stopped +all non-SMF collectd processes before you follow the procedure described +here. To stop collectd the SMF way issue the |svcadm disable +collectd|command. To start collectd the SMF way issue the |svcadm enable +collectd|command. Be aware that setting it this way makes the change +persistent across OS reboots, if you want to enable / disable the +service only temporarily then add |-t| switch after the |enable| / +|disable| keywords. + +And now is time for a grand finale – seeing if SMF can take care of +collectd in case it crashes. See PID of collectd either using |pgrep| or +seeing the contents of the PID file and kill it using |kill|. Then check +with |svcs collectd| command that SMF has restarted collectd soon +afterwards. You should see that the service is once again enabled in the +first column, without your intervention. + +Things that could or should be clarified: + + * How hard is it to correct mistakes in manifests? Does svccfg just + overwrite entries for specified service FMRI or does it require to + delete bad entry (and how to do it?!) and import the correct one? + * How does SMF know that a service has crashed / terminated? I + attended Sun's trainings and the trainer didn't know how to + explain this, we formed a hypothesis that it watches new PIDs + after starting a service or something like that. I think it is a + bad hypothesis, because SMF can watch PID for the startup script + itself but I think not the processes launched inside the script. I + have a slight idea that it is done based on so called contracts. + +------------------------------------------------------------------------ + + + Komentarze do notki “SMF-izing collectd” <#comments> + + + Zostaw odpowiedź + +Nick + +------------------------------------------------------------------------ + + + Archiwum + + * Grudzień 2008 (5) + * Październik 2008 (4) + * Wrzesień 2008 (7) + * Sierpień 2008 (5) + * Lipiec 2008 (12) + * Czerwiec 2008 (11) + * Maj 2008 (3) + * Kwiecień 2008 (10) + * Marzec 2008 (3) + * Luty 2008 (1) + * Styczeń 2008 (1) + * Listopad 2007 (4) + * Październik 2007 (6) + * Wrzesień 2007 (10) + * Sierpień 2007 (3) + * Lipiec 2007 (8) + * Czerwiec 2007 (10) + * Maj 2007 (12) + * Kwiecień 2007 (17) + + + Kategorie + + * Film (8) + * Książki (35) + * Muzyka (15) + * Ogólne (20) + * Polityka (59) + * Sprzedam (5) + * Techblog (20) + * Technikalia (34) + * Wystawy (3) + + + Czytuję + + * ArsTechnica.com + * Fund. Orientacja + * Techblog Jogger'a + * The Register + + + Inne blogi + + * Bloody.Users + * Dandys + * Derin + * Kefir87 + * Klisu + * Kwantowe Krajobrazy + * Paczor + * Prestidigitator + * Remiq + * Torero + * Zdzichubg + + + Inne moje strony + + * www.delphi.org.pl + * www.hosowicz.com + + + Pajacyk.pl + + * Nakarm dzieci! + + + Meta + + * Panel administracyjny + + +------------------------------------------------------------------------ + +phosowicz is powered by Jogger and K2 + by Michael and +Chris , ported by Patryk Zawadzki. + +Notki w RSS + diff --git a/contrib/solaris-smf/collectd b/contrib/solaris-smf/collectd new file mode 100755 index 00000000..5ffdb243 --- /dev/null +++ b/contrib/solaris-smf/collectd @@ -0,0 +1,42 @@ +#!/sbin/sh + +PIDFILE=/opt/collectd/var/run/collectd.pid +DAEMON=/opt/collectd/sbin/collectd + +. /lib/svc/share/smf_include.sh + +case "$1" in + start) + if [ -f $PIDFILE ] ; then + echo "Already running. Stale PID file?" + PID=`cat $PIDFILE` + echo "$PIDFILE contains $PID" + ps -p $PID + exit $SMF_EXIT_ERR_FATAL + fi + $DAEMON + if [ $? -ne 0 ] ; then + echo $DAEMON faild to start + exit $SMF_EXIT_ERR_FATAL + fi + ;; + stop) + PID=`cat $PIDFILE 2>/dev/null` + kill -15 $PID 2>/dev/null + pwait $PID 1> /dev/null 2>/dev/null + ;; + restart) + $0 stop + $0 start + ;; + status) + ps -ef | grep collectd | grep -v status | grep -v grep + ;; + *) + echo "Usage: $0 [ start | stop | restart | status ]" + exit 1 + ;; +esac + + +exit $SMF_EXIT_OK diff --git a/contrib/solaris-smf/collectd.xml b/contrib/solaris-smf/collectd.xml new file mode 100644 index 00000000..d1ae3a46 --- /dev/null +++ b/contrib/solaris-smf/collectd.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 92627b97..39027951 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = +SUBDIRS = libcollectdclient if BUILD_WITH_OWN_LIBIPTC SUBDIRS += libiptc endif @@ -29,14 +29,18 @@ bin_PROGRAMS = collectd-nagios collectd_SOURCES = collectd.c collectd.h \ common.c common.h \ configfile.c configfile.h \ + filter_chain.c filter_chain.h \ + meta_data.c meta_data.h \ plugin.c plugin.h \ utils_avltree.c utils_avltree.h \ utils_cache.c utils_cache.h \ utils_complain.c utils_complain.h \ utils_ignorelist.c utils_ignorelist.h \ utils_llist.c utils_llist.h \ + utils_parse_option.c utils_parse_option.h \ utils_tail_match.c utils_tail_match.h \ utils_match.c utils_match.h \ + utils_subst.c utils_subst.h \ utils_tail.c utils_tail.h \ utils_threshold.c utils_threshold.h \ types_list.c types_list.h @@ -89,6 +93,8 @@ collectd_nagios_LDFLAGS = if BUILD_WITH_LIBSOCKET collectd_nagios_LDFLAGS += -lsocket endif +collectd_nagios_LDADD = libcollectdclient/libcollectdclient.la +collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la pkglib_LTLIBRARIES = @@ -147,6 +153,17 @@ collectd_LDADD += "-dlopen" battery.la collectd_DEPENDENCIES += battery.la endif +if BUILD_PLUGIN_BIND +pkglib_LTLIBRARIES += bind.la +bind_la_SOURCES = bind.c +bind_la_LDFLAGS = -module -avoid-version +bind_la_CFLAGS = $(AM_CFLAGS) \ + $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) +bind_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS) +collectd_LDADD += "-dlopen" bind.la +collectd_DEPENDENCIES += bind.la +endif + if BUILD_PLUGIN_CPU pkglib_LTLIBRARIES += cpu.la cpu_la_SOURCES = cpu.c @@ -183,6 +200,31 @@ collectd_LDADD += "-dlopen" csv.la collectd_DEPENDENCIES += csv.la endif +if BUILD_PLUGIN_CURL +pkglib_LTLIBRARIES += curl.la +curl_la_SOURCES = curl.c +curl_la_LDFLAGS = -module -avoid-version +curl_la_CFLAGS = $(AM_CFLAGS) +curl_la_LIBADD = +collectd_LDADD += "-dlopen" curl.la +if BUILD_WITH_LIBCURL +curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS) +curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS) +endif +collectd_DEPENDENCIES += curl.la +endif + +if BUILD_PLUGIN_DBI +pkglib_LTLIBRARIES += dbi.la +dbi_la_SOURCES = dbi.c \ + utils_db_query.c utils_db_query.h +dbi_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBDBI_CPPFLAGS) +dbi_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBDBI_LDFLAGS) +dbi_la_LIBADD = $(BUILD_WITH_LIBDBI_LIBS) +collectd_LDADD += "-dlopen" dbi.la +collectd_DEPENDENCIES += dbi.la +endif + if BUILD_PLUGIN_DF pkglib_LTLIBRARIES += df.la df_la_SOURCES = df.c utils_mount.c utils_mount.h @@ -244,7 +286,6 @@ endif if BUILD_PLUGIN_EXEC pkglib_LTLIBRARIES += exec.la exec_la_SOURCES = exec.c \ - utils_parse_option.h utils_parse_option.c \ utils_cmd_putnotif.c utils_cmd_putnotif.h \ utils_cmd_putval.c utils_cmd_putval.h exec_la_LDFLAGS = -module -avoid-version @@ -369,6 +410,30 @@ collectd_LDADD += "-dlopen" logfile.la collectd_DEPENDENCIES += logfile.la endif +if BUILD_PLUGIN_MATCH_REGEX +pkglib_LTLIBRARIES += match_regex.la +match_regex_la_SOURCES = match_regex.c +match_regex_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" match_regex.la +collectd_DEPENDENCIES += match_regex.la +endif + +if BUILD_PLUGIN_MATCH_TIMEDIFF +pkglib_LTLIBRARIES += match_timediff.la +match_timediff_la_SOURCES = match_timediff.c +match_timediff_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" match_timediff.la +collectd_DEPENDENCIES += match_timediff.la +endif + +if BUILD_PLUGIN_MATCH_VALUE +pkglib_LTLIBRARIES += match_value.la +match_value_la_SOURCES = match_value.c +match_value_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" match_value.la +collectd_DEPENDENCIES += match_value.la +endif + if BUILD_PLUGIN_MBMON pkglib_LTLIBRARIES += mbmon.la mbmon_la_SOURCES = mbmon.c @@ -528,6 +593,27 @@ collectd_LDADD += "-dlopen" onewire.la collectd_DEPENDENCIES += onewire.la endif +if BUILD_PLUGIN_OPENVPN +pkglib_LTLIBRARIES += openvpn.la +openvpn_la_SOURCES = openvpn.c +openvpn_la_CFLAGS = $(AM_CFLAGS) +openvpn_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" openvpn.la +collectd_DEPENDENCIES += openvpn.la +endif + +if BUILD_PLUGIN_ORACLE +pkglib_LTLIBRARIES += oracle.la +oracle_la_SOURCES = oracle.c \ + utils_db_query.c utils_db_query.h +oracle_la_CFLAGS = $(AM_CFLAGS) +oracle_la_CPPFLAGS = $(BUILD_WITH_ORACLE_CFLAGS) +oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS) +oracle_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" oracle.la +collectd_DEPENDENCIES += oracle.la +endif + if BUILD_PLUGIN_PERL pkglib_LTLIBRARIES += perl.la perl_la_SOURCES = perl.c @@ -537,6 +623,11 @@ perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1 perl_la_CFLAGS = $(AM_CFLAGS) \ $(PERL_CFLAGS) \ -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\" +# Work-around for issues #41 and #42 - Perl 5.10 incorrectly introduced +# __attribute__nonnull__(3) for Perl_load_module(). +if HAVE_BROKEN_PERL_LOAD_MODULE +perl_la_CFLAGS += -Wno-nonnull +endif perl_la_LDFLAGS = -module -avoid-version \ $(PERL_LDFLAGS) collectd_LDADD += "-dlopen" perl.la @@ -559,7 +650,8 @@ endif if BUILD_PLUGIN_POSTGRESQL pkglib_LTLIBRARIES += postgresql.la -postgresql_la_SOURCES = postgresql.c +postgresql_la_SOURCES = postgresql.c \ + utils_db_query.c utils_db_query.h postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS) postgresql_la_LDFLAGS = -module -avoid-version \ $(BUILD_WITH_LIBPQ_LDFLAGS) -lpq @@ -587,9 +679,19 @@ processes_la_LIBADD += -lkvm endif endif +if BUILD_PLUGIN_RRDCACHED +pkglib_LTLIBRARIES += rrdcached.la +rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h +rrdcached_la_LDFLAGS = -module -avoid-version +rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS) +rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS) +collectd_LDADD += "-dlopen" rrdcached.la +collectd_DEPENDENCIES += rrdcached.la +endif + if BUILD_PLUGIN_RRDTOOL pkglib_LTLIBRARIES += rrdtool.la -rrdtool_la_SOURCES = rrdtool.c +rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h rrdtool_la_LDFLAGS = -module -avoid-version rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS) rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS) @@ -679,6 +781,30 @@ collectd_LDADD += "-dlopen" tape.la collectd_DEPENDENCIES += tape.la endif +if BUILD_PLUGIN_TARGET_NOTIFICATION +pkglib_LTLIBRARIES += target_notification.la +target_notification_la_SOURCES = target_notification.c +target_notification_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" target_notification.la +collectd_DEPENDENCIES += target_notification.la +endif + +if BUILD_PLUGIN_TARGET_REPLACE +pkglib_LTLIBRARIES += target_replace.la +target_replace_la_SOURCES = target_replace.c +target_replace_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" target_replace.la +collectd_DEPENDENCIES += target_replace.la +endif + +if BUILD_PLUGIN_TARGET_SET +pkglib_LTLIBRARIES += target_set.la +target_set_la_SOURCES = target_set.c +target_set_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" target_set.la +collectd_DEPENDENCIES += target_set.la +endif + if BUILD_PLUGIN_TCPCONNS pkglib_LTLIBRARIES += tcpconns.la tcpconns_la_SOURCES = tcpconns.c @@ -710,7 +836,6 @@ endif if BUILD_PLUGIN_UNIXSOCK pkglib_LTLIBRARIES += unixsock.la unixsock_la_SOURCES = unixsock.c \ - utils_parse_option.h utils_parse_option.c \ utils_cmd_flush.h utils_cmd_flush.c \ utils_cmd_getval.h utils_cmd_getval.c \ utils_cmd_listval.h utils_cmd_listval.c \ @@ -817,7 +942,7 @@ install-exec-hook: else \ $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \ fi; \ - cp -f $(srcdir)/types.db $(DESTDIR)$(pkglibdir)/; $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL) -m 0644 $(srcdir)/types.db $(DESTDIR)$(pkgdatadir)/types.db; $(INSTALL) -m 0644 $(srcdir)/postgresql_default.conf \ $(DESTDIR)$(pkgdatadir)/postgresql_default.conf; diff --git a/src/apache.c b/src/apache.c index c6bf8add..4fa7aa1b 100644 --- a/src/apache.c +++ b/src/apache.c @@ -55,7 +55,7 @@ static const char *config_keys[] = static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, - void *stream) + void __attribute__((unused)) *stream) { size_t len = size * nmemb; @@ -148,7 +148,7 @@ static int init (void) status = ssnprintf (credentials, sizeof (credentials), "%s:%s", user, (pass == NULL) ? "" : pass); - if (status >= sizeof (credentials)) + if ((status < 0) || ((size_t) status >= sizeof (credentials))) { ERROR ("apache plugin: init: Returning an error " "because the credentials have been " @@ -197,7 +197,6 @@ static void submit_counter (const char *type, const char *type_instance, vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apache", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); @@ -220,7 +219,6 @@ static void submit_gauge (const char *type, const char *type_instance, vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apache", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); diff --git a/src/apcups.c b/src/apcups.c index d20bad3b..a0629d5f 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -364,7 +364,6 @@ static void apc_submit_generic (char *type, char *type_inst, double value) vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); diff --git a/src/apple_sensors.c b/src/apple_sensors.c index d3120276..bdba0ff8 100644 --- a/src/apple_sensors.c +++ b/src/apple_sensors.c @@ -87,7 +87,6 @@ static void as_submit (const char *type, const char *type_instance, vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); diff --git a/src/ascent.c b/src/ascent.c index 6285176a..8829e518 100644 --- a/src/ascent.c +++ b/src/ascent.c @@ -126,7 +126,6 @@ static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */ vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin)); @@ -144,7 +143,7 @@ static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */ } /* }}} int ascent_submit_gauge */ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{ */ - void *stream) + void __attribute__((unused)) *stream) { size_t len = size * nmemb; @@ -175,7 +174,7 @@ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{ static int ascent_submit_players (player_stats_t *ps) /* {{{ */ { - int i; + size_t i; gauge_t value; for (i = 0; i < RACES_LIST_LENGTH; i++) @@ -214,7 +213,7 @@ static int ascent_account_player (player_stats_t *ps, /* {{{ */ { if (pi->race >= 0) { - if ((pi->race >= RACES_LIST_LENGTH) + if (((size_t) pi->race >= RACES_LIST_LENGTH) || (races_list[pi->race] == NULL)) ERROR ("ascent plugin: Ignoring invalid numeric race %i.", pi->race); else @@ -223,7 +222,7 @@ static int ascent_account_player (player_stats_t *ps, /* {{{ */ if (pi->class >= 0) { - if ((pi->class >= CLASSES_LIST_LENGTH) + if (((size_t) pi->class >= CLASSES_LIST_LENGTH) || (classes_list[pi->class] == NULL)) ERROR ("ascent plugin: Ignoring invalid numeric class %i.", pi->class); else @@ -232,7 +231,7 @@ static int ascent_account_player (player_stats_t *ps, /* {{{ */ if (pi->gender >= 0) { - if ((pi->gender >= GENDERS_LIST_LENGTH) + if (((size_t) pi->gender >= GENDERS_LIST_LENGTH) || (genders_list[pi->gender] == NULL)) ERROR ("ascent plugin: Ignoring invalid numeric gender %i.", pi->gender); @@ -550,7 +549,7 @@ static int ascent_init (void) /* {{{ */ status = ssnprintf (credentials, sizeof (credentials), "%s:%s", user, (pass == NULL) ? "" : pass); - if (status >= sizeof (credentials)) + if ((status < 0) || ((size_t) status >= sizeof (credentials))) { ERROR ("ascent plugin: ascent_init: Returning an error because the " "credentials have been truncated."); diff --git a/src/battery.c b/src/battery.c index 70d0486b..b62ad81d 100644 --- a/src/battery.c +++ b/src/battery.c @@ -102,7 +102,6 @@ static void battery_submit (const char *plugin_instance, const char *type, doubl vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "battery", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); @@ -319,8 +318,8 @@ static void get_via_generic_iokit (double *ret_charge, #endif /* HAVE_IOKIT_IOKITLIB_H */ #if KERNEL_LINUX -static int battery_read_acpi (const char *dir, const char *name, - void *user_data) +static int battery_read_acpi (const char __attribute__((unused)) *dir, + const char *name, void __attribute__((unused)) *user_data) { double current = INVALID_VALUE; double voltage = INVALID_VALUE; @@ -441,7 +440,7 @@ static int battery_read (void) /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */ #elif KERNEL_LINUX - static c_complain_t acpi_dir_complaint = C_COMPLAIN_INIT; + static c_complain_t acpi_dir_complaint = C_COMPLAIN_INIT_STATIC; FILE *fh; char buffer[1024]; diff --git a/src/bind.c b/src/bind.c new file mode 100644 index 00000000..44efcfd5 --- /dev/null +++ b/src/bind.c @@ -0,0 +1,1446 @@ +/** + * collectd - src/bind.c + * Copyright (C) 2009 Bruno Prémont + * Copyright (C) 2009 Florian Forster + * + * 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; only version 2 of the License is applicable. + * + * 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Bruno Prémont + * Florian Forster + **/ + +#define _XOPEN_SOURCE 600 /* glibc2 needs this for strptime */ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "configfile.h" + +/* Some versions of libcurl don't include this themselves and then don't have + * fd_set available. */ +#if HAVE_SYS_SELECT_H +# include +#endif + +#include +#include +#include + +#ifndef BIND_DEFAULT_URL +# define BIND_DEFAULT_URL "http://localhost:8053/" +#endif + +/* + * Some types used for the callback functions. `translation_table_ptr_t' and + * `list_info_ptr_t' are passed to the callbacks in the `void *user_data' + * pointer. + */ +typedef int (*list_callback_t) (const char *name, value_t value, + time_t current_time, void *user_data); + +struct cb_view_s +{ + char *name; + + int qtypes; + int resolver_stats; + int cacherrsets; + + char **zones; + size_t zones_num; +}; +typedef struct cb_view_s cb_view_t; + +struct translation_info_s +{ + const char *xml_name; + const char *type; + const char *type_instance; +}; +typedef struct translation_info_s translation_info_t; + +struct translation_table_ptr_s +{ + const translation_info_t *table; + size_t table_length; + const char *plugin_instance; +}; +typedef struct translation_table_ptr_s translation_table_ptr_t; + +struct list_info_ptr_s +{ + const char *plugin_instance; + const char *type; +}; +typedef struct list_info_ptr_s list_info_ptr_t; + +static char *url = NULL; +static int global_opcodes = 1; +static int global_qtypes = 1; +static int global_server_stats = 1; +static int global_zone_maint_stats = 1; +static int global_resolver_stats = 0; +static int global_memory_stats = 1; + +static cb_view_t *views = NULL; +static size_t views_num = 0; + +static CURL *curl = NULL; + +static char *bind_buffer = NULL; +static size_t bind_buffer_size = 0; +static size_t bind_buffer_fill = 0; +static char bind_curl_error[CURL_ERROR_SIZE]; + +/* Translation table for the `nsstats' values. */ +static const translation_info_t nsstats_translation_table[] = /* {{{ */ +{ + /* Requests */ + { "Requestv4", "dns_request", "IPv4" }, + { "Requestv6", "dns_request", "IPv6" }, + { "ReqEdns0", "dns_request", "EDNS0" }, + { "ReqBadEDNSVer", "dns_request", "BadEDNSVer" }, + { "ReqTSIG", "dns_request", "TSIG" }, + { "ReqSIG0", "dns_request", "SIG0" }, + { "ReqBadSIG", "dns_request", "BadSIG" }, + { "ReqTCP", "dns_request", "TCP" }, + /* Rejects */ + { "AuthQryRej", "dns_reject", "authorative" }, + { "RecQryRej", "dns_reject", "recursive" }, + { "XfrRej", "dns_reject", "transfer" }, + { "UpdateRej", "dns_reject", "update" }, + /* Responses */ + { "Response", "dns_response", "normal" }, + { "TruncatedResp", "dns_response", "truncated" }, + { "RespEDNS0", "dns_response", "EDNS0" }, + { "RespTSIG", "dns_response", "TSIG" }, + { "RespSIG0", "dns_response", "SIG0" }, + /* Queries */ + { "QryAuthAns", "dns_query", "authorative" }, + { "QryNoauthAns", "dns_query", "nonauth" }, + { "QryReferral", "dns_query", "referral" }, + { "QryRecursion", "dns_query", "recursion" }, + { "QryDuplicate", "dns_query", "dupliate" }, + { "QryDropped", "dns_query", "dropped" }, + { "QryFailure", "dns_query", "failure" }, + /* Response codes */ + { "QrySuccess", "dns_rcode", "tx-NOERROR" }, + { "QryNxrrset", "dns_rcode", "tx-NXRRSET" }, + { "QrySERVFAIL", "dns_rcode", "tx-SERVFAIL" }, + { "QryFORMERR", "dns_rcode", "tx-FORMERR" }, + { "QryNXDOMAIN", "dns_rcode", "tx-NXDOMAIN" } +#if 0 + { "XfrReqDone", "type", "type_instance" }, + { "UpdateReqFwd", "type", "type_instance" }, + { "UpdateRespFwd", "type", "type_instance" }, + { "UpdateFwdFail", "type", "type_instance" }, + { "UpdateDone", "type", "type_instance" }, + { "UpdateFail", "type", "type_instance" }, + { "UpdateBadPrereq", "type", "type_instance" }, +#endif +}; +static int nsstats_translation_table_length = + STATIC_ARRAY_SIZE (nsstats_translation_table); +/* }}} */ + +/* Translation table for the `zonestats' values. */ +static const translation_info_t zonestats_translation_table[] = /* {{{ */ +{ + /* Notify's */ + { "NotifyOutv4", "dns_notify", "tx-IPv4" }, + { "NotifyOutv6", "dns_notify", "tx-IPv6" }, + { "NotifyInv4", "dns_notify", "rx-IPv4" }, + { "NotifyInv6", "dns_notify", "rx-IPv6" }, + { "NotifyRej", "dns_notify", "rejected" }, + /* SOA/AXFS/IXFS requests */ + { "SOAOutv4", "dns_opcode", "SOA-IPv4" }, + { "SOAOutv6", "dns_opcode", "SOA-IPv6" }, + { "AXFRReqv4", "dns_opcode", "AXFR-IPv4" }, + { "AXFRReqv6", "dns_opcode", "AXFR-IPv6" }, + { "IXFRReqv4", "dns_opcode", "IXFR-IPv4" }, + { "IXFRReqv6", "dns_opcode", "IXFR-IPv6" }, + /* Domain transfers */ + { "XfrSuccess", "dns_transfer", "success" }, + { "XfrFail", "dns_transfer", "failure" } +}; +static int zonestats_translation_table_length = + STATIC_ARRAY_SIZE (zonestats_translation_table); +/* }}} */ + +/* Translation table for the `resstats' values. */ +static const translation_info_t resstats_translation_table[] = /* {{{ */ +{ + /* Generic resolver information */ + { "Queryv4", "dns_query", "IPv4" }, + { "Queryv6", "dns_query", "IPv6" }, + { "Responsev4", "dns_response", "IPv4" }, + { "Responsev6", "dns_response", "IPv6" }, + /* Received response codes */ + { "NXDOMAIN", "dns_rcode", "rx-NXDOMAIN" }, + { "SERVFAIL", "dns_rcode", "rx-SERVFAIL" }, + { "FORMERR", "dns_rcode", "rx-FORMERR" }, + { "OtherError", "dns_rcode", "rx-OTHER" }, + { "EDNS0Fail", "dns_rcode", "rx-EDNS0Fail"}, + /* Received responses */ + { "Mismatch", "dns_response", "mismatch" }, + { "Truncated", "dns_response", "truncated" }, + { "Lame", "dns_response", "lame" }, + { "Retry", "dns_query", "retry" }, +#if 0 + { "GlueFetchv4", "type", "type_instance" }, + { "GlueFetchv6", "type", "type_instance" }, + { "GlueFetchv4Fail", "type", "type_instance" }, + { "GlueFetchv6Fail", "type", "type_instance" }, +#endif + /* DNSSEC information */ + { "ValAttempt", "dns_resolver", "DNSSEC-attempt" }, + { "ValOk", "dns_resolver", "DNSSEC-okay" }, + { "ValNegOk", "dns_resolver", "DNSSEC-negokay" }, + { "ValFail", "dns_resolver", "DNSSEC-fail" } +}; +static int resstats_translation_table_length = + STATIC_ARRAY_SIZE (resstats_translation_table); +/* }}} */ + +/* Translation table for the `memory/summary' values. */ +static const translation_info_t memsummary_translation_table[] = /* {{{ */ +{ + { "TotalUse", "memory", "TotalUse" }, + { "InUse", "memory", "InUse" }, + { "BlockSize", "memory", "BlockSize" }, + { "ContextSize", "memory", "ContextSize" }, + { "Lost", "memory", "Lost" } +}; +static int memsummary_translation_table_length = + STATIC_ARRAY_SIZE (memsummary_translation_table); +/* }}} */ + +static void remove_special (char *buffer, size_t buffer_size) /* {{{ */ +{ + size_t i; + + for (i = 0; i < buffer_size; i++) + { + if (buffer[i] == 0) + return; + if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-')) + buffer[i] = '_'; + } +} /* }}} void remove_special */ + +static void submit (time_t ts, const char *plugin_instance, /* {{{ */ + const char *type, const char *type_instance, value_t value) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + values[0] = value; + + vl.values = values; + vl.values_len = 1; + vl.time = ts; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "bind", sizeof(vl.plugin)); + if (plugin_instance) { + sstrncpy(vl.plugin_instance, plugin_instance, + sizeof(vl.plugin_instance)); + remove_special (vl.plugin_instance, sizeof (vl.plugin_instance)); + } + sstrncpy(vl.type, type, sizeof(vl.type)); + if (type_instance) { + sstrncpy(vl.type_instance, type_instance, + sizeof(vl.type_instance)); + remove_special (vl.plugin_instance, sizeof (vl.plugin_instance)); + } + plugin_dispatch_values(&vl); +} /* }}} void submit */ + +static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */ + size_t nmemb, void __attribute__((unused)) *stream) +{ + size_t len = size * nmemb; + + if (len <= 0) + return (len); + + if ((bind_buffer_fill + len) >= bind_buffer_size) + { + char *temp; + + temp = realloc(bind_buffer, bind_buffer_fill + len + 1); + if (temp == NULL) + { + ERROR ("bind plugin: realloc failed."); + return (0); + } + bind_buffer = temp; + bind_buffer_size = bind_buffer_fill + len + 1; + } + + memcpy (bind_buffer + bind_buffer_fill, (char *) buf, len); + bind_buffer_fill += len; + bind_buffer[bind_buffer_fill] = 0; + + return (len); +} /* }}} size_t bind_curl_callback */ + +/* + * Callback, that's called with a translation table. + * (Plugin instance is fixed, type and type instance come from lookup table.) + */ +static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */ + time_t current_time, void *user_data) +{ + translation_table_ptr_t *table = (translation_table_ptr_t *) user_data; + size_t i; + + if (table == NULL) + return (-1); + + for (i = 0; i < table->table_length; i++) + { + if (strcmp (table->table[i].xml_name, name) != 0) + continue; + + submit (current_time, + table->plugin_instance, + table->table[i].type, + table->table[i].type_instance, + value); + break; + } + + return (0); +} /* }}} int bind_xml_table_callback */ + +/* + * Callback, that's used for lists. + * (Plugin instance and type are fixed, xml name is used as type instance.) + */ +static int bind_xml_list_callback (const char *name, /* {{{ */ + value_t value, time_t current_time, void *user_data) +{ + list_info_ptr_t *list_info = (list_info_ptr_t *) user_data; + + if (list_info == NULL) + return (-1); + + submit (current_time, + list_info->plugin_instance, + list_info->type, + /* type instance = */ name, + value); + + return (0); +} /* }}} int bind_xml_list_callback */ + +static int bind_xml_read_counter (xmlDoc *doc, xmlNode *node, /* {{{ */ + counter_t *ret_value) +{ + char *str_ptr, *end_ptr; + long long int value; + + str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) + { + ERROR ("bind plugin: bind_xml_read_counter: xmlNodeListGetString failed."); + return (-1); + } + + errno = 0; + value = strtoll (str_ptr, &end_ptr, 10); + xmlFree(str_ptr); + if (str_ptr == end_ptr || errno) + { + if (errno && (value < 0)) + ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with underflow."); + else if (errno && (value > 0)) + ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with overflow."); + else + ERROR ("bind plugin: bind_xml_read_counter: strtoll failed."); + return (-1); + } + + *ret_value = value; + return (0); +} /* }}} int bind_xml_read_counter */ + +static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ + gauge_t *ret_value) +{ + char *str_ptr, *end_ptr; + double value; + + str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) + { + ERROR ("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); + return (-1); + } + + errno = 0; + value = strtod (str_ptr, &end_ptr); + xmlFree(str_ptr); + if (str_ptr == end_ptr || errno) + { + if (errno && (value < 0)) + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with underflow."); + else if (errno && (value > 0)) + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with overflow."); + else + ERROR ("bind plugin: bind_xml_read_gauge: strtod failed."); + return (-1); + } + + *ret_value = (gauge_t) value; + return (0); +} /* }}} int bind_xml_read_gauge */ + +static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ + xmlDoc *doc, xmlXPathContext *xpathCtx, time_t *ret_value) +{ + xmlXPathObject *xpathObj = NULL; + xmlNode *node; + char *str_ptr; + char *tmp; + struct tm tm; + + xpathObj = xmlXPathEvalExpression (BAD_CAST xpath_expression, xpathCtx); + if (xpathObj == NULL) + { + ERROR ("bind plugin: Unable to evaluate XPath expression `%s'.", + xpath_expression); + return (-1); + } + + if ((xpathObj->nodesetval == NULL) || (xpathObj->nodesetval->nodeNr < 1)) + { + xmlXPathFreeObject (xpathObj); + return (-1); + } + + if (xpathObj->nodesetval->nodeNr != 1) + { + NOTICE ("bind plugin: Evaluating the XPath expression `%s' returned " + "%i nodes. Only handling the first one.", + xpath_expression, xpathObj->nodesetval->nodeNr); + } + + node = xpathObj->nodesetval->nodeTab[0]; + + if (node->xmlChildrenNode == NULL) + { + ERROR ("bind plugin: bind_xml_read_timestamp: " + "node->xmlChildrenNode == NULL"); + xmlXPathFreeObject (xpathObj); + return (-1); + } + + str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) + { + ERROR ("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed."); + xmlXPathFreeObject (xpathObj); + return (-1); + } + + memset (&tm, 0, sizeof(tm)); + tmp = strptime (str_ptr, "%Y-%m-%dT%T", &tm); + xmlFree(str_ptr); + if (tmp == NULL) + { + ERROR ("bind plugin: bind_xml_read_timestamp: strptime failed."); + xmlXPathFreeObject (xpathObj); + return (-1); + } + + *ret_value = mktime(&tm); + + xmlXPathFreeObject (xpathObj); + return (0); +} /* }}} int bind_xml_read_timestamp */ + +/* + * bind_parse_generic_name_value + * + * Reads statistics in the form: + * + * QUERY + * 123 + * + */ +static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ */ + list_callback_t list_callback, + void *user_data, + xmlDoc *doc, xmlXPathContext *xpathCtx, + time_t current_time, int ds_type) +{ + xmlXPathObject *xpathObj = NULL; + int num_entries; + int i; + + xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + if (xpathObj == NULL) + { + ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", + xpath_expression); + return (-1); + } + + num_entries = 0; + /* Iterate over all matching nodes. */ + for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) + { + xmlNode *name_node = NULL; + xmlNode *counter = NULL; + xmlNode *parent; + xmlNode *child; + + parent = xpathObj->nodesetval->nodeTab[i]; + DEBUG ("bind plugin: bind_parse_generic_name_value: parent->name = %s;", + (char *) parent->name); + + /* Iterate over all child nodes. */ + for (child = parent->xmlChildrenNode; + child != NULL; + child = child->next) + { + if (child->type != XML_ELEMENT_NODE) + continue; + + if (xmlStrcmp (BAD_CAST "name", child->name) == 0) + name_node = child; + else if (xmlStrcmp (BAD_CAST "counter", child->name) == 0) + counter = child; + } + + if ((name_node != NULL) && (counter != NULL)) + { + char *name = (char *) xmlNodeListGetString (doc, + name_node->xmlChildrenNode, 1); + value_t value; + int status; + + if (ds_type == DS_TYPE_GAUGE) + status = bind_xml_read_gauge (doc, counter, &value.gauge); + else + status = bind_xml_read_counter (doc, counter, &value.counter); + if (status != 0) + continue; + + status = (*list_callback) (name, value, current_time, user_data); + if (status == 0) + num_entries++; + + xmlFree (name); + } + } + + DEBUG ("bind plugin: Found %d %s for XPath expression `%s'", + num_entries, (num_entries == 1) ? "entry" : "entries", + xpath_expression); + + xmlXPathFreeObject(xpathObj); + + return (0); +} /* }}} int bind_parse_generic_name_value */ + +/* + * bind_parse_generic_value_list + * + * Reads statistics in the form: + * + * 123 + * 234 + * 345 + * : + * + */ +static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ */ + list_callback_t list_callback, + void *user_data, + xmlDoc *doc, xmlXPathContext *xpathCtx, + time_t current_time, int ds_type) +{ + xmlXPathObject *xpathObj = NULL; + int num_entries; + int i; + + xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + if (xpathObj == NULL) + { + ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", + xpath_expression); + return (-1); + } + + num_entries = 0; + /* Iterate over all matching nodes. */ + for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) + { + xmlNode *child; + + /* Iterate over all child nodes. */ + for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; + child != NULL; + child = child->next) + { + char *node_name; + value_t value; + int status; + + if (child->type != XML_ELEMENT_NODE) + continue; + + node_name = (char *) child->name; + + if (ds_type == DS_TYPE_GAUGE) + status = bind_xml_read_gauge (doc, child, &value.gauge); + else + status = bind_xml_read_counter (doc, child, &value.counter); + if (status != 0) + continue; + + status = (*list_callback) (node_name, value, current_time, user_data); + if (status == 0) + num_entries++; + } + } + + DEBUG ("bind plugin: Found %d %s for XPath expression `%s'", + num_entries, (num_entries == 1) ? "entry" : "entries", + xpath_expression); + + xmlXPathFreeObject(xpathObj); + + return (0); +} /* }}} int bind_parse_generic_value_list */ + +static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, + time_t current_time) +{ + xmlXPathObject *path_obj; + char *zone_name = NULL; + int i; + size_t j; + + path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx); + if (path_obj == NULL) + { + ERROR ("bind plugin: xmlXPathEvalExpression failed."); + return (-1); + } + + for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++) + { + zone_name = (char *) xmlNodeListGetString (doc, + path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1); + if (zone_name != NULL) + break; + } + + if (zone_name == NULL) + { + ERROR ("bind plugin: Could not determine zone name."); + xmlXPathFreeObject (path_obj); + return (-1); + } + + for (j = 0; j < view->zones_num; j++) + { + if (strcasecmp (zone_name, view->zones[j]) == 0) + break; + } + + xmlFree (zone_name); + zone_name = NULL; + + if (j >= views_num) + { + xmlXPathFreeObject (path_obj); + return (0); + } + + zone_name = view->zones[j]; + + DEBUG ("bind plugin: bind_xml_stats_handle_zone: Found zone `%s'.", + zone_name); + + { /* Parse the tag {{{ */ + char plugin_instance[DATA_MAX_NAME_LEN]; + translation_table_ptr_t table_ptr = + { + nsstats_translation_table, + nsstats_translation_table_length, + plugin_instance + }; + + ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-zone-%s", + view->name, zone_name); + + bind_parse_generic_value_list (/* xpath = */ "counters", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, path_ctx, current_time, DS_TYPE_COUNTER); + } /* }}} */ + + xmlXPathFreeObject (path_obj); + + return (0); +} /* }}} int bind_xml_stats_handle_zone */ + +static int bind_xml_stats_search_zones (int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, + time_t current_time) +{ + xmlXPathObject *zone_nodes = NULL; + xmlXPathContext *zone_path_context; + int i; + + zone_path_context = xmlXPathNewContext (doc); + if (zone_path_context == NULL) + { + ERROR ("bind plugin: xmlXPathNewContext failed."); + return (-1); + } + + zone_nodes = xmlXPathEvalExpression (BAD_CAST "zones/zone", path_ctx); + if (zone_nodes == NULL) + { + ERROR ("bind plugin: Cannot find any tags."); + xmlXPathFreeContext (zone_path_context); + return (-1); + } + + for (i = 0; i < zone_nodes->nodesetval->nodeNr; i++) + { + xmlNode *node; + + node = zone_nodes->nodesetval->nodeTab[i]; + assert (node != NULL); + + zone_path_context->node = node; + + bind_xml_stats_handle_zone (version, doc, zone_path_context, node, view, + current_time); + } + + xmlXPathFreeObject (zone_nodes); + xmlXPathFreeContext (zone_path_context); + return (0); +} /* }}} int bind_xml_stats_search_zones */ + +static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, time_t current_time) +{ + xmlXPathObject *path_obj; + char *view_name = NULL; + cb_view_t *view; + int i; + size_t j; + + path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx); + if (path_obj == NULL) + { + ERROR ("bind plugin: xmlXPathEvalExpression failed."); + return (-1); + } + + for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++) + { + view_name = (char *) xmlNodeListGetString (doc, + path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1); + if (view_name != NULL) + break; + } + + if (view_name == NULL) + { + ERROR ("bind plugin: Could not determine view name."); + xmlXPathFreeObject (path_obj); + return (-1); + } + + for (j = 0; j < views_num; j++) + { + if (strcasecmp (view_name, views[j].name) == 0) + break; + } + + xmlFree (view_name); + xmlXPathFreeObject (path_obj); + + view_name = NULL; + path_obj = NULL; + + if (j >= views_num) + return (0); + + view = views + j; + + DEBUG ("bind plugin: bind_xml_stats_handle_view: Found view `%s'.", + view->name); + + if (view->qtypes != 0) /* {{{ */ + { + char plugin_instance[DATA_MAX_NAME_LEN]; + list_info_ptr_t list_info = + { + plugin_instance, + /* type = */ "dns_qtype_gauge" + }; + + ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-qtypes", + view->name); + + bind_parse_generic_name_value (/* xpath = */ "rdtype", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, + doc, path_ctx, current_time, DS_TYPE_COUNTER); + } /* }}} */ + + if (view->resolver_stats != 0) /* {{{ */ + { + char plugin_instance[DATA_MAX_NAME_LEN]; + translation_table_ptr_t table_ptr = + { + resstats_translation_table, + resstats_translation_table_length, + plugin_instance + }; + + ssnprintf (plugin_instance, sizeof (plugin_instance), + "%s-resolver_stats", view->name); + + bind_parse_generic_name_value ("resstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, path_ctx, current_time, DS_TYPE_COUNTER); + } /* }}} */ + + if (view->cacherrsets != 0) /* {{{ */ + { + char plugin_instance[DATA_MAX_NAME_LEN]; + list_info_ptr_t list_info = + { + plugin_instance, + /* type = */ "dns_qtype_gauge" + }; + + ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-cache_rr_sets", + view->name); + + bind_parse_generic_name_value (/* xpath = */ "cache/rrset", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, + doc, path_ctx, current_time, DS_TYPE_GAUGE); + } /* }}} */ + + if (view->zones_num > 0) + bind_xml_stats_search_zones (version, doc, path_ctx, node, view, + current_time); + + return (0); +} /* }}} int bind_xml_stats_handle_view */ + +static int bind_xml_stats_search_views (int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time) +{ + xmlXPathObject *view_nodes = NULL; + xmlXPathContext *view_path_context; + int i; + + view_path_context = xmlXPathNewContext (doc); + if (view_path_context == NULL) + { + ERROR ("bind plugin: xmlXPathNewContext failed."); + return (-1); + } + + view_nodes = xmlXPathEvalExpression (BAD_CAST "views/view", xpathCtx); + if (view_nodes == NULL) + { + ERROR ("bind plugin: Cannot find any tags."); + xmlXPathFreeContext (view_path_context); + return (-1); + } + + for (i = 0; i < view_nodes->nodesetval->nodeNr; i++) + { + xmlNode *node; + + node = view_nodes->nodesetval->nodeTab[i]; + assert (node != NULL); + + view_path_context->node = node; + + bind_xml_stats_handle_view (version, doc, view_path_context, node, + current_time); + } + + xmlXPathFreeObject (view_nodes); + xmlXPathFreeContext (view_path_context); + return (0); +} /* }}} int bind_xml_stats_search_views */ + +static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, xmlNode *statsnode) +{ + time_t current_time = 0; + int status; + + xpathCtx->node = statsnode; + + /* TODO: Check `server/boot-time' to recognize server restarts. */ + + status = bind_xml_read_timestamp ("server/current-time", + doc, xpathCtx, ¤t_time); + if (status != 0) + { + ERROR ("bind plugin: Reading `server/current-time' failed."); + return (-1); + } + DEBUG ("bind plugin: Current server time is %i.", (int) current_time); + + /* XPath: server/requests/opcode + * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ... + * Layout: + * + * A + * 1 + * + * : + */ + if (global_opcodes != 0) + { + list_info_ptr_t list_info = + { + /* plugin instance = */ "global-opcodes", + /* type = */ "dns_opcode" + }; + + bind_parse_generic_name_value (/* xpath = */ "server/requests/opcode", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + + /* XPath: server/queries-in/rdtype + * Variables: RESERVED0, A, NS, CNAME, SOA, MR, PTR, HINFO, MX, TXT, RP, + * X25, PX, AAAA, LOC, SRV, NAPTR, A6, DS, RRSIG, NSEC, DNSKEY, + * SPF, TKEY, IXFR, AXFR, ANY, ..., Others + * Layout: + * + * A + * 1 + * + * : + */ + if (global_qtypes != 0) + { + list_info_ptr_t list_info = + { + /* plugin instance = */ "global-qtypes", + /* type = */ "dns_qtype" + }; + + bind_parse_generic_name_value (/* xpath = */ "server/queries-in/rdtype", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + + /* XPath: server/nsstats, server/nsstat + * Variables: Requestv4, Requestv6, ReqEdns0, ReqBadEDNSVer, ReqTSIG, + * ReqSIG0, ReqBadSIG, ReqTCP, AuthQryRej, RecQryRej, XfrRej, + * UpdateRej, Response, TruncatedResp, RespEDNS0, RespTSIG, + * RespSIG0, QrySuccess, QryAuthAns, QryNoauthAns, QryReferral, + * QryNxrrset, QrySERVFAIL, QryFORMERR, QryNXDOMAIN, QryRecursion, + * QryDuplicate, QryDropped, QryFailure, XfrReqDone, UpdateReqFwd, + * UpdateRespFwd, UpdateFwdFail, UpdateDone, UpdateFail, + * UpdateBadPrereq + * Layout v1: + * + * 1 + * 0 + * : + * + * Layout v2: + * + * Requestv4 + * 1 + * + * + * Requestv6 + * 0 + * + * : + */ + if (global_server_stats) + { + translation_table_ptr_t table_ptr = + { + nsstats_translation_table, + nsstats_translation_table_length, + /* plugin_instance = */ "global-server_stats" + }; + + if (version == 1) + { + bind_parse_generic_value_list ("server/nsstats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + else + { + bind_parse_generic_name_value ("server/nsstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + } + + /* XPath: server/zonestats, server/zonestat + * Variables: NotifyOutv4, NotifyOutv6, NotifyInv4, NotifyInv6, NotifyRej, + * SOAOutv4, SOAOutv6, AXFRReqv4, AXFRReqv6, IXFRReqv4, IXFRReqv6, + * XfrSuccess, XfrFail + * Layout v1: + * + * 0 + * 0 + * : + * + * Layout v2: + * + * NotifyOutv4 + * 0 + * + * + * NotifyOutv6 + * 0 + * + * : + */ + if (global_zone_maint_stats) + { + translation_table_ptr_t table_ptr = + { + zonestats_translation_table, + zonestats_translation_table_length, + /* plugin_instance = */ "global-zone_maint_stats" + }; + + if (version == 1) + { + bind_parse_generic_value_list ("server/zonestats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + else + { + bind_parse_generic_name_value ("server/zonestat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + } + + /* XPath: server/resstats + * Variables: Queryv4, Queryv6, Responsev4, Responsev6, NXDOMAIN, SERVFAIL, + * FORMERR, OtherError, EDNS0Fail, Mismatch, Truncated, Lame, + * Retry, GlueFetchv4, GlueFetchv6, GlueFetchv4Fail, + * GlueFetchv6Fail, ValAttempt, ValOk, ValNegOk, ValFail + * Layout v1: + * + * 0 + * 0 + * : + * + * Layout v2: + * + * Queryv4 + * 0 + * + * + * Queryv6 + * 0 + * + * : + */ + if (global_resolver_stats != 0) + { + translation_table_ptr_t table_ptr = + { + resstats_translation_table, + resstats_translation_table_length, + /* plugin_instance = */ "global-resolver_stats" + }; + + if (version == 1) + { + bind_parse_generic_value_list ("server/resstats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + else + { + bind_parse_generic_name_value ("server/resstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_COUNTER); + } + } + + /* XPath: memory/summary + * Variables: TotalUse, InUse, BlockSize, ContextSize, Lost + * Layout: v2: + * + * 6587096 + * 1345424 + * 5505024 + * 3732456 + * 0 + * + */ + if (global_memory_stats != 0) + { + translation_table_ptr_t table_ptr = + { + memsummary_translation_table, + memsummary_translation_table_length, + /* plugin_instance = */ "global-memory_stats" + }; + + bind_parse_generic_value_list ("memory/summary", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, + doc, xpathCtx, current_time, DS_TYPE_GAUGE); + } + + if (views_num > 0) + bind_xml_stats_search_views (version, doc, xpathCtx, statsnode, + current_time); + + return 0; +} /* }}} int bind_xml_stats */ + +static int bind_xml (const char *data) /* {{{ */ +{ + xmlDoc *doc = NULL; + xmlXPathContext *xpathCtx = NULL; + xmlXPathObject *xpathObj = NULL; + int ret = -1; + int i; + + doc = xmlParseMemory (data, strlen (data)); + if (doc == NULL) + { + ERROR ("bind plugin: xmlParseMemory failed."); + return (-1); + } + + xpathCtx = xmlXPathNewContext (doc); + if (xpathCtx == NULL) + { + ERROR ("bind plugin: xmlXPathNewContext failed."); + xmlFreeDoc (doc); + return (-1); + } + + xpathObj = xmlXPathEvalExpression (BAD_CAST "/isc/bind/statistics", xpathCtx); + if (xpathObj == NULL) + { + ERROR ("bind plugin: Cannot find the tag."); + xmlXPathFreeContext (xpathCtx); + xmlFreeDoc (doc); + return (-1); + } + else if (xpathObj->nodesetval == NULL) + { + ERROR ("bind plugin: xmlXPathEvalExpression failed."); + xmlXPathFreeObject (xpathObj); + xmlXPathFreeContext (xpathCtx); + xmlFreeDoc (doc); + return (-1); + } + + for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) + { + xmlNode *node; + char *attr_version; + int parsed_version = 0; + + node = xpathObj->nodesetval->nodeTab[i]; + assert (node != NULL); + + attr_version = (char *) xmlGetProp (node, BAD_CAST "version"); + if (attr_version == NULL) + { + NOTICE ("bind plugin: Found tag doesn't have a " + "`version' attribute."); + continue; + } + DEBUG ("bind plugin: Found: ", attr_version); + + /* At the time this plugin was written, version "1.0" was used by + * BIND 9.5.0, version "2.0" was used by BIND 9.5.1 and 9.6.0. We assume + * that "1.*" and "2.*" don't introduce structural changes, so we just + * check for the first two characters here. */ + if (strncmp ("1.", attr_version, strlen ("1.")) == 0) + parsed_version = 1; + else if (strncmp ("2.", attr_version, strlen ("2.")) == 0) + parsed_version = 2; + else + { + /* TODO: Use the complaint mechanism here. */ + NOTICE ("bind plugin: Found tag with version `%s'. " + "Unfortunately I have no clue how to parse that. " + "Please open a bug report for this.", attr_version); + xmlFree (attr_version); + continue; + } + + ret = bind_xml_stats (parsed_version, + doc, xpathCtx, node); + + xmlFree (attr_version); + /* One node ought to be enough. */ + break; + } + + xmlXPathFreeObject (xpathObj); + xmlXPathFreeContext (xpathCtx); + xmlFreeDoc (doc); + + return (ret); +} /* }}} int bind_xml */ + +static int bind_config_set_bool (const char *name, int *var, /* {{{ */ + oconfig_item_t *ci) +{ + if ((ci->values_num != 1) || ( ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) + { + WARNING ("bind plugin: The `%s' option needs " + "exactly one boolean argument.", name); + return (-1); + } + + if (ci->values[0].value.boolean) + *var = 1; + else + *var = 0; + return 0; +} /* }}} int bind_config_set_bool */ + +static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */ + oconfig_item_t *ci) +{ + char **tmp; + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("bind plugin: The `Zone' option needs " + "exactly one string argument."); + return (-1); + } + + tmp = (char **) realloc (view->zones, + sizeof (char *) * (view->zones_num + 1)); + if (tmp == NULL) + { + ERROR ("bind plugin: realloc failed."); + return (-1); + } + view->zones = tmp; + + view->zones[view->zones_num] = strdup (ci->values[0].value.string); + if (view->zones[view->zones_num] == NULL) + { + ERROR ("bind plugin: strdup failed."); + return (-1); + } + view->zones_num++; + + return (0); +} /* }}} int bind_config_add_view_zone */ + +static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */ +{ + cb_view_t *tmp; + int i; + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("bind plugin: `View' blocks need exactly one string argument."); + return (-1); + } + + tmp = (cb_view_t *) realloc (views, sizeof (*views) * (views_num + 1)); + if (tmp == NULL) + { + ERROR ("bind plugin: realloc failed."); + return (-1); + } + views = tmp; + tmp = views + views_num; + + memset (tmp, 0, sizeof (*tmp)); + tmp->qtypes = 1; + tmp->resolver_stats = 1; + tmp->cacherrsets = 1; + tmp->zones = NULL; + tmp->zones_num = 0; + + tmp->name = strdup (ci->values[0].value.string); + if (tmp->name == NULL) + { + ERROR ("bind plugin: strdup failed."); + free (tmp); + return (-1); + } + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("QTypes", child->key) == 0) + bind_config_set_bool ("QTypes", &tmp->qtypes, child); + else if (strcasecmp ("ResolverStats", child->key) == 0) + bind_config_set_bool ("ResolverStats", &tmp->resolver_stats, child); + else if (strcasecmp ("CacheRRSets", child->key) == 0) + bind_config_set_bool ("CacheRRSets", &tmp->cacherrsets, child); + else if (strcasecmp ("Zone", child->key) == 0) + bind_config_add_view_zone (tmp, child); + else + { + WARNING ("bind plugin: Unknown configuration option " + "`%s' in view `%s' will be ignored.", child->key, tmp->name); + } + } /* for (i = 0; i < ci->children_num; i++) */ + + views_num++; + return (0); +} /* }}} int bind_config_add_view */ + +static int bind_config (oconfig_item_t *ci) /* {{{ */ +{ + int i; + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Url", child->key) == 0) { + if ((child->values_num != 1) || (child->values[0].type != OCONFIG_TYPE_STRING)) + { + WARNING ("bind plugin: The `Url' option needs " + "exactly one string argument."); + return (-1); + } + + url = strdup (child->values[0].value.string); + } else if (strcasecmp ("OpCodes", child->key) == 0) + bind_config_set_bool ("OpCodes", &global_opcodes, child); + else if (strcasecmp ("QTypes", child->key) == 0) + bind_config_set_bool ("QTypes", &global_qtypes, child); + else if (strcasecmp ("ServerStats", child->key) == 0) + bind_config_set_bool ("ServerStats", &global_server_stats, child); + else if (strcasecmp ("ZoneMaintStats", child->key) == 0) + bind_config_set_bool ("ZoneMaintStats", &global_zone_maint_stats, child); + else if (strcasecmp ("ResolverStats", child->key) == 0) + bind_config_set_bool ("ResolverStats", &global_resolver_stats, child); + else if (strcasecmp ("MemoryStats", child->key) == 0) + bind_config_set_bool ("MemoryStats", &global_memory_stats, child); + else if (strcasecmp ("View", child->key) == 0) + bind_config_add_view (child); + else + { + WARNING ("bind plugin: Unknown configuration option " + "`%s' will be ignored.", child->key); + } + } + + return (0); +} /* }}} int bind_config */ + +static int bind_init (void) /* {{{ */ +{ + if (curl != NULL) + return (0); + + curl = curl_easy_init (); + if (curl == NULL) + { + ERROR ("bind plugin: bind_init: curl_easy_init failed."); + return (-1); + } + + curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback); + curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION); + curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error); + curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL); + + return (0); +} /* }}} int bind_init */ + +static int bind_read (void) /* {{{ */ +{ + int status; + + if (curl == NULL) + { + ERROR ("bind plugin: I don't have a CURL object."); + return (-1); + } + + bind_buffer_fill = 0; + if (curl_easy_perform (curl) != 0) + { + ERROR ("bind plugin: curl_easy_perform failed: %s", + bind_curl_error); + return (-1); + } + + status = bind_xml (bind_buffer); + if (status != 0) + return (-1); + else + return (0); +} /* }}} int bind_read */ + +static int bind_shutdown (void) /* {{{ */ +{ + if (curl != NULL) + { + curl_easy_cleanup (curl); + curl = NULL; + } + + return (0); +} /* }}} int bind_shutdown */ + +void module_register (void) +{ + plugin_register_complex_config ("bind", bind_config); + plugin_register_init ("bind", bind_init); + plugin_register_read ("bind", bind_read); + plugin_register_shutdown ("bind", bind_shutdown); +} /* void module_register */ + +/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */ diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod index d935c70d..b95779dd 100644 --- a/src/collectd-exec.pod +++ b/src/collectd-exec.pod @@ -83,7 +83,7 @@ plugin within collectd. I identifies the type and number of values data-sets is available in the B file. See L for a description of the format of this file. -The I is an optional list of I, where each option if a +The I is an optional list of I, where each option is a key-value-pair. A list of currently understood options can be found below, all other options will be ignored. Values that contain spaces must be quoted with double quotes. diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c index ca72a68c..0c480a06 100644 --- a/src/collectd-nagios.c +++ b/src/collectd-nagios.c @@ -1,15 +1,50 @@ -#include "config.h" +/** + * collectd-nagios - src/collectd-nagios.c + * Copyright (C) 2008 Florian octo Forster + * + * 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; only version 2 of the License is applicable. + * + * 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +/* Set to C99 and POSIX code */ +#if COLLECT_STANDARDS +# include "standards.h" +#endif /* COLLECT_STANDARDS */ + +#if !defined(__GNUC__) || !__GNUC__ +# define __attribute__(x) /**/ +#endif #include #include #include #include #include +#include #include #include #include +#include "libcollectdclient/client.h" + /* * This is copied directly from collectd.h. Make changes there! */ @@ -46,6 +81,7 @@ #define CON_NONE 0 #define CON_AVERAGE 1 #define CON_SUM 2 +#define CON_PERCENTAGE 3 struct range_s { @@ -69,19 +105,91 @@ static int consolitation_g = CON_NONE; static char **match_ds_g = NULL; static int match_ds_num_g = 0; -static int ignore_ds (const char *name) +/* `strdup' is an XSI extension. I don't want to pull in all of XSI just for + * that, so here's an own implementation.. It's easy enough. The GCC attributes + * are supposed to get good performance.. -octo */ +__attribute__((malloc, nonnull (1))) +static char *cn_strdup (const char *str) /* {{{ */ +{ + size_t strsize; + char *ret; + + strsize = strlen (str) + 1; + ret = (char *) malloc (strsize); + if (ret != NULL) + memcpy (ret, str, strsize); + return (ret); +} /* }}} char *cn_strdup */ + +static int filter_ds (size_t *values_num, + double **values, char ***values_names) { - int i; + gauge_t *new_values; + char **new_names; + + size_t i; if (match_ds_g == NULL) - return (0); + return (RET_OKAY); + + new_values = (gauge_t *)calloc (match_ds_num_g, sizeof (*new_values)); + if (new_values == NULL) + { + fprintf (stderr, "malloc failed: %s\n", strerror (errno)); + return (RET_UNKNOWN); + } + + new_names = (char **)calloc (match_ds_num_g, sizeof (*new_names)); + if (new_names == NULL) + { + fprintf (stderr, "malloc failed: %s\n", strerror (errno)); + free (new_values); + return (RET_UNKNOWN); + } + + for (i = 0; i < (size_t) match_ds_num_g; i++) + { + size_t j; + + /* match_ds_g keeps pointers into argv but the names will be freed */ + new_names[i] = cn_strdup (match_ds_g[i]); + if (new_names[i] == NULL) + { + fprintf (stderr, "cn_strdup failed: %s\n", strerror (errno)); + free (new_values); + for (j = 0; j < i; j++) + free (new_names[j]); + free (new_names); + return (RET_UNKNOWN); + } + + for (j = 0; j < *values_num; j++) + if (strcasecmp (new_names[i], (*values_names)[j]) == 0) + break; + + if (j == *values_num) + { + printf ("ERROR: DS `%s' is not available.\n", new_names[i]); + free (new_values); + for (j = 0; j <= i; j++) + free (new_names[j]); + free (new_names); + return (RET_CRITICAL); + } + + new_values[i] = (*values)[j]; + } - for (i = 0; i < match_ds_num_g; i++) - if (strcasecmp (match_ds_g[i], name) == 0) - return (0); + free (*values); + for (i = 0; i < *values_num; i++) + free ((*values_names)[i]); + free (*values_names); - return (1); -} /* int ignore_ds */ + *values = new_values; + *values_names = new_names; + *values_num = match_ds_num_g; + return (RET_OKAY); +} /* int filter_ds */ static void parse_range (char *string, range_t *range) { @@ -124,7 +232,7 @@ static void parse_range (char *string, range_t *range) range->max = atof (max_ptr); } /* void parse_range */ -int match_range (range_t *range, double value) +static int match_range (range_t *range, double value) { int ret = 0; @@ -134,164 +242,7 @@ int match_range (range_t *range, double value) ret = 1; return (((ret - range->invert) == 0) ? 0 : 1); -} - -static int get_values (int *ret_values_num, double **ret_values, - char ***ret_values_names) -{ - struct sockaddr_un sa; - int status; - int fd; - FILE *fh_in, *fh_out; - char buffer[4096]; - - int values_num; - double *values; - char **values_names; - - int i; - int j; - - fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - { - fprintf (stderr, "socket failed: %s\n", - strerror (errno)); - return (-1); - } - - memset (&sa, '\0', sizeof (sa)); - sa.sun_family = AF_UNIX; - strncpy (sa.sun_path, socket_file_g, - sizeof (sa.sun_path) - 1); - - status = connect (fd, (struct sockaddr *) &sa, sizeof (sa)); - if (status != 0) - { - fprintf (stderr, "connect failed: %s\n", - strerror (errno)); - return (-1); - } - - fh_in = fdopen (fd, "r"); - if (fh_in == NULL) - { - fprintf (stderr, "fdopen failed: %s\n", - strerror (errno)); - close (fd); - return (-1); - } - - fh_out = fdopen (fd, "w"); - if (fh_out == NULL) - { - fprintf (stderr, "fdopen failed: %s\n", - strerror (errno)); - fclose (fh_in); - return (-1); - } - - fprintf (fh_out, "GETVAL %s/%s\n", hostname_g, value_string_g); - fflush (fh_out); - - if (fgets (buffer, sizeof (buffer), fh_in) == NULL) - { - fprintf (stderr, "fgets failed: %s\n", - strerror (errno)); - fclose (fh_in); - fclose (fh_out); - return (-1); - } - - { - char *ptr = strchr (buffer, ' '); - - if (ptr != NULL) - *ptr = '\0'; - - values_num = atoi (buffer); - if (values_num < 1) - return (-1); - } - - values = (double *) malloc (values_num * sizeof (double)); - if (values == NULL) - { - fprintf (stderr, "malloc failed: %s\n", - strerror (errno)); - return (-1); - } - - values_names = (char **) malloc (values_num * sizeof (char *)); - if (values_names == NULL) - { - fprintf (stderr, "malloc failed: %s\n", - strerror (errno)); - free (values); - return (-1); - } - memset (values_names, 0, values_num * sizeof (char *)); - - i = 0; /* index of the values returned by the server */ - j = 0; /* number of values in `values_names' and `values' */ - while (fgets (buffer, sizeof (buffer), fh_in) != NULL) - { - do /* while (0) */ - { - char *key; - char *value; - char *endptr; - - key = buffer; - - value = strchr (key, '='); - if (value == NULL) - { - fprintf (stderr, "Cannot parse line: %s\n", buffer); - break; - } - *value = 0; - value++; - - if (ignore_ds (key) != 0) - break; - - endptr = NULL; - errno = 0; - values[j] = strtod (value, &endptr); - if ((endptr == value) || (errno != 0)) - { - fprintf (stderr, "Could not parse buffer " - "as number: %s\n", value); - break; - } - - values_names[j] = strdup (key); - if (values_names[j] == NULL) - { - fprintf (stderr, "strdup failed.\n"); - break; - } - j++; - } while (0); - - i++; - if (i >= values_num) - break; - } - /* Set `values_num' to the number of values actually stored in the - * array. */ - values_num = j; - - fclose (fh_in); fh_in = NULL; fd = -1; - fclose (fh_out); fh_out = NULL; - - *ret_values_num = values_num; - *ret_values = values; - *ret_values_names = values_names; - - return (0); -} /* int get_values */ +} /* int match_range */ static void usage (const char *name) { @@ -304,7 +255,7 @@ static void usage (const char *name) " -d Select the DS to examine. May be repeated to examine multiple\n" " DSes. By default all DSes are used.\n" " -g Method to use to consolidate several DSes.\n" - " Valid arguments are `none', `average' and `sum'\n" + " See below for a list of valid arguments.\n" " -H Hostname to query the values for.\n" " -c Critical range\n" " -w Warning range\n" @@ -315,17 +266,21 @@ static void usage (const char *name) " average: Calculate the average of all matching DSes and apply the\n" " warning- and critical-ranges to the calculated average.\n" " sum: Apply the ranges to the sum of all DSes.\n" + " percentage: Apply the ranges to the ratio (in percent) of the first value\n" + " and the sum of all values." "\n", name); exit (1); } /* void usage */ -int do_check_con_none (int values_num, double *values, char **values_names) +static int do_check_con_none (size_t values_num, + double *values, char **values_names) { - int i; - int num_critical = 0; int num_warning = 0; int num_okay = 0; + const char *status_str = "UNKNOWN"; + int status_code = RET_UNKNOWN; + size_t i; for (i = 0; i < values_num; i++) { @@ -339,30 +294,49 @@ int do_check_con_none (int values_num, double *values, char **values_names) num_okay++; } - printf ("%i critical, %i warning, %i okay", + if ((num_critical == 0) && (num_warning == 0) && (num_okay == 0)) + { + printf ("WARNING: No defined values found\n"); + return (RET_WARNING); + } + else if ((num_critical == 0) && (num_warning == 0)) + { + status_str = "OKAY"; + status_code = RET_OKAY; + } + else if (num_critical == 0) + { + status_str = "WARNING"; + status_code = RET_WARNING; + } + else + { + status_str = "CRITICAL"; + status_code = RET_CRITICAL; + } + + printf ("%s: %i critical, %i warning, %i okay", status_str, num_critical, num_warning, num_okay); if (values_num > 0) { printf (" |"); for (i = 0; i < values_num; i++) - printf (" %s=%lf;;;;", values_names[i], values[i]); + printf (" %s=%g;;;;", values_names[i], values[i]); } printf ("\n"); - if ((num_critical != 0) || (values_num == 0)) - return (RET_CRITICAL); - else if (num_warning != 0) - return (RET_WARNING); - - return (RET_OKAY); + return (status_code); } /* int do_check_con_none */ -int do_check_con_average (int values_num, double *values, char **values_names) +static int do_check_con_average (size_t values_num, + double *values, char **values_names) { - int i; + size_t i; double total; int total_num; double average; + const char *status_str = "UNKNOWN"; + int status_code = RET_UNKNOWN; total = 0.0; total_num = 0; @@ -376,30 +350,45 @@ int do_check_con_average (int values_num, double *values, char **values_names) } if (total_num == 0) - average = NAN; - else - average = total / total_num; - printf ("%lf average |", average); - for (i = 0; i < values_num; i++) - printf (" %s=%lf;;;;", values_names[i], values[i]); - - if (total_num == 0) + { + printf ("WARNING: No defined values found\n"); return (RET_WARNING); + } - if (isnan (average) - || match_range (&range_critical_g, average)) - return (RET_CRITICAL); + average = total / total_num; + + if (match_range (&range_critical_g, average) != 0) + { + status_str = "CRITICAL"; + status_code = RET_CRITICAL; + } else if (match_range (&range_warning_g, average) != 0) - return (RET_WARNING); + { + status_str = "WARNING"; + status_code = RET_WARNING; + } + else + { + status_str = "OKAY"; + status_code = RET_OKAY; + } - return (RET_OKAY); + printf ("%s: %g average |", status_str, average); + for (i = 0; i < values_num; i++) + printf (" %s=%g;;;;", values_names[i], values[i]); + printf ("\n"); + + return (status_code); } /* int do_check_con_average */ -int do_check_con_sum (int values_num, double *values, char **values_names) +static int do_check_con_sum (size_t values_num, + double *values, char **values_names) { - int i; + size_t i; double total; int total_num; + const char *status_str = "UNKNOWN"; + int status_code = RET_UNKNOWN; total = 0.0; total_num = 0; @@ -420,47 +409,150 @@ int do_check_con_sum (int values_num, double *values, char **values_names) if (match_range (&range_critical_g, total) != 0) { - printf ("CRITICAL: Sum = %lf\n", total); - return (RET_CRITICAL); + status_str = "CRITICAL"; + status_code = RET_CRITICAL; } else if (match_range (&range_warning_g, total) != 0) { - printf ("WARNING: Sum = %lf\n", total); - return (RET_WARNING); + status_str = "WARNING"; + status_code = RET_WARNING; } else { - printf ("OKAY: Sum = %lf\n", total); - return (RET_OKAY); + status_str = "OKAY"; + status_code = RET_OKAY; } - return (RET_UNKNOWN); + printf ("%s: %g sum |", status_str, total); + for (i = 0; i < values_num; i++) + printf (" %s=%g;;;;", values_names[i], values[i]); + printf ("\n"); + + return (status_code); } /* int do_check_con_sum */ -int do_check (void) +static int do_check_con_percentage (size_t values_num, + double *values, char **values_names) +{ + size_t i; + double sum = 0.0; + double percentage; + + const char *status_str = "UNKNOWN"; + int status_code = RET_UNKNOWN; + + if ((values_num < 1) || (isnan (values[0]))) + { + printf ("WARNING: The first value is not defined\n"); + return (RET_WARNING); + } + + for (i = 0; i < values_num; i++) + if (!isnan (values[i])) + sum += values[i]; + + if (sum == 0.0) + { + printf ("WARNING: Values sum up to zero\n"); + return (RET_WARNING); + } + + percentage = 100.0 * values[0] / sum; + + if (match_range (&range_critical_g, percentage) != 0) + { + status_str = "CRITICAL"; + status_code = RET_CRITICAL; + } + else if (match_range (&range_warning_g, percentage) != 0) + { + status_str = "WARNING"; + status_code = RET_WARNING; + } + else + { + status_str = "OKAY"; + status_code = RET_OKAY; + } + + printf ("%s: %lf percent |", status_str, percentage); + for (i = 0; i < values_num; i++) + printf (" %s=%lf;;;;", values_names[i], values[i]); + return (status_code); +} /* int do_check_con_percentage */ + +static int do_check (void) { - double *values; + lcc_connection_t *connection; + gauge_t *values; char **values_names; - int values_num; + size_t values_num; + char address[1024]; + char ident_str[1024]; + lcc_identifier_t ident; + size_t i; + int status; + + snprintf (address, sizeof (address), "unix:%s", socket_file_g); + address[sizeof (address) - 1] = 0; + + snprintf (ident_str, sizeof (ident_str), "%s/%s", + hostname_g, value_string_g); + ident_str[sizeof (ident_str) - 1] = 0; - if (get_values (&values_num, &values, &values_names) != 0) + connection = NULL; + status = lcc_connect (address, &connection); + if (status != 0) { - fputs ("ERROR: Cannot get values from daemon\n", stdout); + printf ("ERROR: Connecting to daemon at %s failed.\n", + socket_file_g); return (RET_CRITICAL); } + memset (&ident, 0, sizeof (ident)); + status = lcc_string_to_identifier (connection, &ident, ident_str); + if (status != 0) + { + printf ("ERROR: Creating an identifier failed: %s.\n", + lcc_strerror (connection)); + LCC_DESTROY (connection); + return (RET_CRITICAL); + } + + status = lcc_getval (connection, &ident, + &values_num, &values, &values_names); + if (status != 0) + { + printf ("ERROR: Retrieving values from the daemon failed: %s.\n", + lcc_strerror (connection)); + LCC_DESTROY (connection); + return (RET_CRITICAL); + } + + LCC_DESTROY (connection); + + status = filter_ds (&values_num, &values, &values_names); + if (status != RET_OKAY) + return (status); + + status = RET_UNKNOWN; if (consolitation_g == CON_NONE) - return (do_check_con_none (values_num, values, values_names)); + status = do_check_con_none (values_num, values, values_names); else if (consolitation_g == CON_AVERAGE) - return (do_check_con_average (values_num, values, values_names)); + status = do_check_con_average (values_num, values, values_names); else if (consolitation_g == CON_SUM) - return (do_check_con_sum (values_num, values, values_names)); + status = do_check_con_sum (values_num, values, values_names); + else if (consolitation_g == CON_PERCENTAGE) + status = do_check_con_percentage (values_num, values, values_names); free (values); - free (values_names); /* FIXME? */ + if (values_names != NULL) + for (i = 0; i < values_num; i++) + free (values_names[i]); + free (values_names); - return (RET_UNKNOWN); -} + return (status); +} /* int do_check */ int main (int argc, char **argv) { @@ -504,8 +596,14 @@ int main (int argc, char **argv) consolitation_g = CON_AVERAGE; else if (strcasecmp (optarg, "sum") == 0) consolitation_g = CON_SUM; + else if (strcasecmp (optarg, "percentage") == 0) + consolitation_g = CON_PERCENTAGE; else + { + fprintf (stderr, "Unknown consolidation function `%s'.\n", + optarg); usage (argv[0]); + } break; case 'd': { @@ -520,10 +618,10 @@ int main (int argc, char **argv) return (RET_UNKNOWN); } match_ds_g = tmp; - match_ds_g[match_ds_num_g] = strdup (optarg); + match_ds_g[match_ds_num_g] = cn_strdup (optarg); if (match_ds_g[match_ds_num_g] == NULL) { - fprintf (stderr, "strdup failed: %s\n", + fprintf (stderr, "cn_strdup failed: %s\n", strerror (errno)); return (RET_UNKNOWN); } @@ -537,7 +635,10 @@ int main (int argc, char **argv) if ((socket_file_g == NULL) || (value_string_g == NULL) || (hostname_g == NULL)) + { + fprintf (stderr, "Missing required arguments.\n"); usage (argv[0]); + } return (do_check ()); } /* int main */ diff --git a/src/collectd-nagios.pod b/src/collectd-nagios.pod index 49800255..c6347eac 100644 --- a/src/collectd-nagios.pod +++ b/src/collectd-nagios.pod @@ -63,6 +63,12 @@ The warning and critical ranges are applied to the average of all values. The warning and critical ranges are applied to the sum of all values. +=item B + +The warning and critical ranges are applied to the ratio (in percent) of the +first value and the sum of all values. A warning is returned if the first +value is not defined or if all values sum up to zero. + =back =item B<-c> I @@ -96,7 +102,7 @@ As usual for Nagios plugins, this program writes a short, one line status message to STDOUT and signals success or failure with it's return value. It exits with a return value of B<0> for I, B<1> for I and B<2> for I. If the values are not available or some other error occurred, -it returns B<3> for I. +it returns B<3> for I. =head1 SEE ALSO diff --git a/src/collectd-perl.pod b/src/collectd-perl.pod index c3fcb108..acb8abda 100644 --- a/src/collectd-perl.pod +++ b/src/collectd-perl.pod @@ -198,6 +198,7 @@ layout looks like this: { values => [123, 0.5], time => time (), + interval => $interval_g, host => $hostname_g, plugin => 'myplugin', type => 'myplugin', @@ -208,7 +209,9 @@ layout looks like this: =item Notification A notification is one structure defining the severity, time and message of the -status message as well as an identification of a data instance: +status message as well as an identification of a data instance. Also, it +includes an optional list of user-defined meta information represented as +(name, value) pairs: { severity => NOTIF_FAILURE || NOTIF_WARNING || NOTIF_OKAY, @@ -218,7 +221,30 @@ status message as well as an identification of a data instance: plugin => 'myplugin', type => 'mytype', plugin_instance => '', - type_instance => '' + type_instance => '', + meta => [ { name => , value => }, ... ] + } + +=item Match-Proc + +A match-proc is one structure storing the callbacks of a "match" of the filter +chain infrastructure. The general layout looks like this: + + { + create => 'my_create', + destroy => 'my_destroy', + match => 'my_match' + } + +=item Target-Proc + +A target-proc is one structure storing the callbacks of a "target" of the +filter chain infrastructure. The general layout looks like this: + + { + create => 'my_create', + destroy => 'my_destroy', + invoke => 'my_invoke' } =back @@ -341,12 +367,26 @@ as the first argument to B. This syntax is still supported for backwards compatibility but has been deprecated and will be removed in some future version of collectd. +=item B ([B => I<...>][, B => I<...>], +B => I<...>) + +Calls the write function of the given I with the provided I and I. In contrast to B, it does +not update collectd's internal cache and bypasses the filter mechanism (see +L for details). If the B argument has been omitted, +the values will be dispatched to all registered write plugins. If the +B argument has been omitted, the required data sets are looked up +according to the C member in the appropriate value list. The value of +all three arguments may either be a single scalar or a reference to an array. +If the B argument has been specified, the number of data sets has to +equal the number of specified value lists. + =item B ([B => I][, B => I<...>][, B => I<...>]) Flush one or more plugins. I and the specified I are passed on to the registered flush-callbacks. If omitted, the timeout defaults -to C<-1>. The identifier defaults to the undefined value. If the I +to C<-1>. The identifier defaults to the undefined value. If the B argument has been specified, only named plugins will be flushed. The value of the B and B arguments may either be a string or a reference to an array of strings. @@ -385,6 +425,68 @@ B, B and B respectively as I. =back +The following function provides the filter chain C-interface to Perl-modules. +It is exported by the ":filter_chain" export tag (see the section "EXPORTS" +below). + +=over 4 + +=item B (I, I, I) + +Registers filter chain callbacks with collectd. + +I may be any of: + +=over 4 + +=item FC_MATCH + +=item FC_TARGET + +=back + +I is the name of the match or target. By this name, the callbacks are +identified in the configuration file when specifying a B or B +block (see L for details). + +I is a hash reference. The hash includes up to three callbacks: an +optional constructor (B) and destructor (B) and a mandatory +B or B callback. B is called whenever processing an +appropriate match, while B is called whenever processing an +appropriate target (see the section "FILTER CONFIGURATION" in +L for details). Just like any other callbacks, filter chain +callbacks are identified by the function name rather than a function pointer +because Perl does not support to share references to subroutines between +threads. The following arguments are passed to the callbacks: + +=over 4 + +=item create + +The arguments passed are I and I. See above for the +layout of the config-item data-type. I is a reference to a scalar +value that may be used to store any information specific to this particular +instance. The daemon does not care about this information at all. It's for the +plugin's use only. + +=item destroy + +The only argument passed is I which is a reference to the user data +initialized in the B callback. This callback may be used to cleanup +instance-specific information and settings. + +=item match, invoke + +The arguments passed are I, I, I and I. +See above for the layout of the data-set and value-list data-types. I is +a pointer to an array of meta information, just like the B member of the +notification data-type (see above). I is a reference to the user +data initialized in the B callback. + +=back + +=back + =head1 GLOBAL VARIABLES =over 4 @@ -491,6 +593,34 @@ available (B<:all> will export all of them): =back +=item B<:filter_chain> + +=over 4 + +=item B + +=item B + +=item B + +=item B + +=item B + +=item B + +=back + +=item B<:fc_types> + +=over 4 + +=item B + +=item B + +=back + =item B<:notif> =over 4 @@ -526,7 +656,7 @@ Any Perl plugin will start similar to: use Collectd qw( :all ); -A very simple read function will look like: +A very simple read function might look like: sub foobar_read { @@ -536,7 +666,7 @@ A very simple read function will look like: return 1; } -A very simple write function will look like: +A very simple write function might look like: sub foobar_write { @@ -547,13 +677,27 @@ A very simple write function will look like: return 1; } +A very simple match callback might look like: + + sub foobar_match + { + my ($ds, $vl, $meta, $user_data) = @_; + if (matches($ds, $vl)) { + return FC_MATCH_MATCHES; + } else { + return FC_MATCH_NO_MATCH; + } + } + To register those functions with collectd: plugin_register (TYPE_READ, "foobar", "foobar_read"); plugin_register (TYPE_WRITE, "foobar", "foobar_write"); + fc_register (FC_MATCH, "foobar", "foobar_match"); + See the section "DATA TYPES" above for a complete documentation of the data -types used by the read and write functions. +types used by the read, write and match functions. =head1 NOTES diff --git a/src/collectd.c b/src/collectd.c index 9526ec91..576abef4 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -47,7 +47,7 @@ kstat_ctl_t *kc; static int loop = 0; -static void *do_flush (void *arg) +static void *do_flush (void __attribute__((unused)) *arg) { INFO ("Flushing all data."); plugin_flush (NULL, -1, NULL); @@ -56,17 +56,17 @@ static void *do_flush (void *arg) return NULL; } -static void sig_int_handler (int signal) +static void sig_int_handler (int __attribute__((unused)) signal) { loop++; } -static void sig_term_handler (int signal) +static void sig_term_handler (int __attribute__((unused)) signal) { loop++; } -static void sig_usr1_handler (int signal) +static void sig_usr1_handler (int __attribute__((unused)) signal) { pthread_t thread; pthread_attr_t attr; @@ -253,6 +253,7 @@ static void exit_usage (int status) " -C Configuration file.\n" " Default: "CONFIGFILE"\n" " -t Test config and exit.\n" + " -T Test plugin read and exit.\n" " -P PID-file.\n" " Default: "PIDFILE"\n" #if COLLECT_DAEMON @@ -300,6 +301,7 @@ static int do_loop (void) { struct timeval tv_now; struct timeval tv_next; + struct timeval tv_wait; struct timespec ts_wait; while (loop == 0) @@ -330,14 +332,17 @@ static int do_loop (void) return (-1); } - if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0) + if (timeval_cmp (tv_next, tv_now, &tv_wait) <= 0) { - WARNING ("Not sleeping because " - "`timeval_sub_timespec' returned " - "non-zero!"); + WARNING ("Not sleeping because the next interval is " + "%i.%06i seconds in the past!", + (int) tv_wait.tv_sec, (int) tv_wait.tv_usec); continue; } + ts_wait.tv_sec = tv_wait.tv_sec; + ts_wait.tv_nsec = (long) (1000 * tv_wait.tv_usec); + while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) == -1)) { if (errno != EINTR) @@ -398,19 +403,21 @@ int main (int argc, char **argv) struct sigaction sig_pipe_action; char *configfile = CONFIGFILE; int test_config = 0; + int test_readall = 0; const char *basedir; #if COLLECT_DAEMON struct sigaction sig_chld_action; pid_t pid; int daemonize = 1; #endif + int exit_status = 0; /* read options */ while (1) { int c; - c = getopt (argc, argv, "htC:" + c = getopt (argc, argv, "htTC:" #if COLLECT_DAEMON "fP:" #endif @@ -427,6 +434,13 @@ int main (int argc, char **argv) case 't': test_config = 1; break; + case 'T': + test_readall = 1; + global_option_set ("ReadThreads", "-1"); +#if COLLECT_DAEMON + daemonize = 0; +#endif /* COLLECT_DAEMON */ + break; #if COLLECT_DAEMON case 'P': global_option_set ("PIDFile", optarg); @@ -580,10 +594,20 @@ int main (int argc, char **argv) * run the actual loops */ do_init (); - do_loop (); + + if (test_readall) + { + if (plugin_read_all_once () != 0) + exit_status = 1; + } + else + { + INFO ("Initialization complete, entering read-loop."); + do_loop (); + } /* close syslog */ - INFO ("Exiting normally"); + INFO ("Exiting normally."); do_shutdown (); @@ -592,5 +616,5 @@ int main (int argc, char **argv) pidfile_remove (); #endif /* COLLECT_DAEMON */ - return (0); + return (exit_status); } /* int main */ diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 9f14257b..8a059122 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -9,7 +9,7 @@ FQDNLookup true #BaseDir "@prefix@/var/lib/@PACKAGE_NAME@" #PIDFile "@prefix@/var/run/@PACKAGE_NAME@.pid" #PluginDir "@prefix@/lib/@PACKAGE_NAME@" -#TypesDB "@prefix@/lib/@PACKAGE_NAME@/types.db" +#TypesDB "@prefix@/share/@PACKAGE_NAME@/types.db" #Interval 10 #ReadThreads 5 @@ -31,9 +31,12 @@ FQDNLookup true @BUILD_PLUGIN_APPLE_SENSORS_TRUE@LoadPlugin apple_sensors @BUILD_PLUGIN_ASCENT_TRUE@LoadPlugin ascent @BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery +@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind @BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu @BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq @BUILD_PLUGIN_CSV_TRUE@LoadPlugin csv +@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl +@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi @BUILD_PLUGIN_DF_TRUE@LoadPlugin df @BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk @BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns @@ -63,11 +66,14 @@ FQDNLookup true @BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd @BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut @BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire +@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn +@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle @BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl @BUILD_PLUGIN_PING_TRUE@LoadPlugin ping @BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql @BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns @BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes +@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached @BUILD_PLUGIN_RRDTOOL_TRUE@LoadPlugin rrdtool @BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors @BUILD_PLUGIN_SERIAL_TRUE@LoadPlugin serial @@ -80,7 +86,7 @@ FQDNLookup true @BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal @BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock @BUILD_PLUGIN_USERS_TRUE@LoadPlugin users -@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid +#LoadPlugin uuid @BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem @BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver @BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless @@ -105,11 +111,65 @@ FQDNLookup true # CACert "/etc/ssl/ca.crt" # +# +# URL "http://localhost:8053/" +# OpCodes true +# QTypes true +# +# ServerStats true +# ZoneMaintStats true +# ResolverStats false +# MemoryStats true +# +# +# QTypes true +# ResolverStats true +# CacheRRSets true +# +# Zone "127.in-addr.arpa/IN" +# +# + # # DataDir "@prefix@/var/lib/@PACKAGE_NAME@/csv" # StoreRates false # +# +# +# URL "http://finance.google.com/finance?q=NYSE%3AAMD" +# User "foo" +# Password "bar" +# +# Regex "]*> *([0-9]*\\.[0-9]+) *" +# DSType "GaugeAverage" +# Type "stock_value" +# Instance "AMD" +# +# +# + +# +# +# Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value FROM customers_tbl" +# +# Type "gauge" +# InstancesFrom "c_key" +# ValuesFrom "c_value" +# +# +# +# Driver "mysql" +# DriverOption "host" "localhost" +# DriverOption "username" "collectd" +# DriverOption "password" "AeXohy0O" +# DriverOption "dbname" "custdb0" +# #SelectDB "custdb0" +# Query "num_of_customers" +# #Query "..." +# +# + # # Device "/dev/hda1" # Device "192.168.0.2:/mnt/nfs" @@ -146,6 +206,7 @@ FQDNLookup true # Name "*.conf" # MTime "-5m" # Size "+10k" +# Recursive true # # @@ -258,6 +319,27 @@ FQDNLookup true # IgnoreSelected false # +# +# StatusFile "/etc/openvpn/openvpn-status.log" +# + +# +# +# Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category" +# +# Type "gauge" +# InstancesFrom "category" +# ValuesFrom "value" +# +# +# +# ConnectID "db01" +# Username "oracle" +# Password "secret" +# Query "out_of_stock" +# +# + # # IncludeDir "/my/include/path" # BaseName "Collectd::Plugin" @@ -277,26 +359,41 @@ FQDNLookup true # # -# Query "SELECT magic, spells FROM wizard WHERE host = $1;" +# Statement "SELECT magic FROM wizard WHERE host = $1;" # Param hostname -# Column gauge magic -# Column counter spells +# +# Type gauge +# InstancePrefix "magic" +# ValuesFrom magic +# +# +# +# Statement "SELECT COUNT(type) AS count, type \ +# FROM (SELECT CASE \ +# WHEN resolved = 'epoch' THEN 'open' \ +# ELSE 'resolved' END AS type \ +# FROM tickets) type \ +# GROUP BY type;" +# +# Type counter +# InstancePrefix "rt36_tickets" +# InstancesFrom "type" +# ValuesFrom "count" +# # -# # # Host "hostname" -# Port 5432 +# Port "5432" # User "username" # Password "secret" -# # SSLMode "prefer" # KRBSrvName "kerberos_service_name" -# # Query magic # -# # # Service "service_name" +# Query backend # predefined +# Query rt36_tickets # # @@ -318,6 +415,13 @@ FQDNLookup true # Process "name" # +# +# DaemonAddress "unix:/tmp/rrdcached.sock" +# DataDir "@prefix@/var/lib/@PACKAGE_NAME@/rrd" +# CreateFiles true +# CollectStatistics true +# + # # DataDir "@prefix@/var/lib/@PACKAGE_NAME@/rrd" # CacheTimeout 120 @@ -423,3 +527,27 @@ FQDNLookup true # Verbose false # +# * * * * * * * * * * * * * +# * FILTER CONFIGURATION * +# * * * * * * * * * * * * * + +# The following configures collectd's filtering mechanism. Before changing +# anything in this section, please read the `FILTER CONFIGURATION' section in +# the collectd.conf(5) manual page. + +# Load required matches: +#@BUILD_PLUGIN_MATCH_REGEX_TRUE@LoadPlugin match_regex +#@BUILD_PLUGIN_MATCH_VALUE_TRUE@LoadPlugin match_value +#@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@LoadPlugin match_timediff + +# Load required targets: +#@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@LoadPlugin target_notification +#@BUILD_PLUGIN_TARGET_REPLACE_TRUE@LoadPlugin target_replace +#@BUILD_PLUGIN_TARGET_SET_TRUE@LoadPlugin target_set + +# The following block demonstrates the default behavior if no filtering is +# configured at all: All values will be sent to all available write plugins. + +# +# Target "write" +# diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 895a443e..43946bdf 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -126,6 +126,14 @@ The sample config file that is installed with Cinstall> includes a line which sets this option, though, so that default installations will have this setting enabled. +=item B I + +=item B I + +Configure the name of the "pre-cache chain" and the "post-cache chain". Please +see L below on information on chains and how these +setting change the daemon's behavior. + =back =head1 PLUGIN OPTIONS @@ -257,6 +265,150 @@ and are checked by default depends on the distribution you use. =back +=head2 Plugin C + +Starting with BIND 9.5.0, the most widely used DNS server software provides +extensive statistics about queries, responses and lots of other information. +The bind plugin retrieves this information that's encoded in XML and provided +via HTTP and submits the values to collectd. + +To use this plugin, you first need to tell BIND to make this information +available. This is done with the C configuration option: + + statistics-channels { + inet localhost port 8053; + }; + +The configuration follows the grouping that can be seen when looking at the +data with an XSLT compatible viewer, such as a modern web browser. It's +probably a good idea to make yourself familiar with the provided values, so you +can understand what the collected statistics actually mean. + +Synopsis: + + + URL "http://localhost:8053/" + OpCodes true + QTypes true + + ServerStats true + ZoneMaintStats true + ResolverStats false + MemoryStats true + + + QTypes true + ResolverStats true + CacheRRSets true + + Zone "127.in-addr.arpa/IN" + + + +The bind plugin accepts the following configuration options: + +=over 4 + +=item B I + +URL from which to retrieve the XML data. If not specified, +C will be used. + +=item B I|I + +When enabled, statistics about the I<"OpCodes">, for example the number of +C packets, are collected. + +Default: Enabled. + +=item B I|I + +When enabled, the number of I queries by query types (for example +C, C, C) is collected. + +Default: Enabled. + +=item B I|I + +Collect global server statistics, such as requests received over IPv4 and IPv6, +successful queries, and failed updates. + +Default: Enabled. + +=item B I|I + +Collect zone maintenance statistics, mostly information about notifications +(zone updates) and zone transfers. + +Default: Enabled. + +=item B I|I + +Collect resolver statistics, i.Ee. statistics about outgoing requests +(e.Eg. queries over IPv4, lame servers). Since the global resolver +counters apparently were removed in BIND 9.5.1 and 9.6.0, this is disabled by +default. Use the B option within a B block +instead for the same functionality. + +Default: Disabled. + +=item B + +Collect global memory statistics. + +Default: Enabled. + +=item B I + +Collect statistics about a specific I<"view">. BIND can behave different, +mostly depending on the source IP-address of the request. These different +configurations are called "views". If you don't use this feature, you most +likely are only interested in the C<_default> view. + +Within a EBEIE block, you can specify which +information you want to collect about a view. If no B block is +configured, no detailed view statistics will be collected. + +=over 4 + +=item B I|I + +If enabled, the number of I queries by query type (e.Eg. C, +C) is collected. + +Default: Enabled. + +=item B I|I + +Collect resolver statistics, i.Ee. statistics about outgoing requests +(e.Eg. queries over IPv4, lame servers). + +Default: Enabled. + +=item B I|I + +If enabled, the number of entries (I<"RR sets">) in the view's cache by query +type is collected. Negative entries (queries which resulted in an error, for +example names that do not exist) are reported with a leading exclamation mark, +e.Eg. "!A". + +Default: Enabled. + +=item B I + +When given, collect detailed information about the given zone in the view. The +information collected if very similar to the global B information +(see above). + +You can repeat this option to collect detailed information about multiple +zones. + +By default no detailed zone information is collected. + +=back + +=back + =head2 Plugin C This plugin doesn't have any options. It reads @@ -273,6 +425,9 @@ installed and an "cpu governor" (that's a kernel module) is loaded. Set the directory to store CSV-files under. Per default CSV-files are generated beneath the daemon's working directory, i.Ee. the B. +The special strings B and B can be used to write to the standard +output and standard error channels, respectively. This, of course, only makes +much sense when collectd is running in foreground- or non-daemon-mode. =item B B @@ -282,6 +437,316 @@ number. =back +=head2 Plugin C + +The curl plugin uses the B (L) to read web pages +and the match infrastructure (the same code used by the tail plugin) to use +regular expressions with the received data. + +The following example will read the current value of AMD stock from google's +finance page and dispatch the value to collectd. + + + + URL "http://finance.google.com/finance?q=NYSE%3AAMD" + User "foo" + Password "bar" + + Regex "]*> *([0-9]*\\.[0-9]+) *" + DSType "GaugeAverage" + # Note: `stock_value' is not a standard type. + Type "stock_value" + Instance "AMD" + + + + +In the B block, there may be one or more B blocks, each defining +a web page and one or more "matches" to be performed on the returned data. The +string argument to the B block is used as plugin instance. + +The following options are valid within B blocks: + +=over 4 + +=item B I + +URL of the web site to retrieve. Since a regular expression will be used to +extract information from this data, non-binary data is a big plus here ;) + +=item B I + +Username to use if authorization is required to read the page. + +=item B I + +Password to use if authorization is required to read the page. + +=item B B|B + +Enable or disable peer SSL certificate verification. See +L for details. Enabled by default. + +=item B B|B + +Enable or disable peer host name verification. If enabled, the plugin checks if +the C or a C field of the SSL certificate +matches the host name provided by the B option. If this identity check +fails, the connection is aborted. Obviously, only works when connecting to a +SSL enabled server. Enabled by default. + +=item B I + +File that holds one or more SSL certificates. If you want to use HTTPS you will +possibly need this option. What CA certificates come bundled with C +and are checked by default depends on the distribution you use. + +=item BMatchE> + +One or more B blocks that define how to match information in the data +returned by C. The C plugin uses the same infrastructure that's +used by the C plugin, so please see the documentation of the C +plugin below on how matches are defined. + +=back + +=head2 Plugin C + +This plugin uses the B library (L) to +connect to various databases, execute I statements and read back the +results. I is an acronym for "database interface" in case you were +wondering about the name. You can configure how each column is to be +interpreted and the plugin will generate one or more data sets from each row +returned according to these rules. + +Because the plugin is very generic, the configuration is a little more complex +than those of other plugins. It usually looks something like this: + + + + Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category" + # Use with MySQL 5.0.0 or later + MinVersion 50000 + + Type "gauge" + InstancePrefix "out_of_stock" + InstancesFrom "category" + ValuesFrom "value" + + + + Driver "mysql" + DriverOption "host" "localhost" + DriverOption "username" "collectd" + DriverOption "password" "aZo6daiw" + DriverOption "dbname" "prod_info" + SelectDB "prod_info" + Query "out_of_stock" + + + +The configuration above defines one query with one result and one database. The +query is then linked to the database with the B option I the +BDatabaseE> block. You can have any number of queries and databases +and you can also use the B statement to split up the configuration +file in multiple, smaller files. However, the BQueryE> block I +precede the BDatabaseE> blocks, because the file is interpreted from +top to bottom! + +The following is a complete list of options: + +=head3 B blocks + +Query blocks define I statements and how the returned data should be +interpreted. They are identified by the name that is given in the opening line +of the block. Thus the name needs to be unique. Other than that, the name is +not used in collectd. + +In each B block, there is one or more B blocks. B blocks +define which column holds which value or instance information. You can use +multiple B blocks to create multiple values from one returned row. This +is especially useful, when queries take a long time and sending almost the same +query again and again is not desirable. + +Example: + + + Statement "select station, temperature, humidity from environment" + + Type "temperature" + # InstancePrefix "foo" + InstancesFrom "station" + ValuesFrom "temperature" + + + Type "humidity" + InstancesFrom "station" + ValuesFrom "humidity" + + + +The following options are accepted: + +=over 4 + +=item B I + +Sets the statement that should be executed on the server. This is B +interpreted by collectd, but simply passed to the database server. Therefore, +the SQL dialect that's used depends on the server collectd is connected to. + +The query has to return at least two columns, one for the instance and one +value. You cannot omit the instance, even if the statement is guaranteed to +always return exactly one line. In that case, you can usually specify something +like this: + + Statement "SELECT \"instance\", COUNT(*) AS value FROM table" + +(That works with MySQL but may not be valid SQL according to the spec. If you +use a more strict database server, you may have to select from a dummy table or +something.) + +Please note that some databases, for example B, will fail if you +include a semicolon at the end of the statement. + +=item B I + +=item B I + +Only use this query for the specified database version. You can use these +options to provide multiple queries with the same name but with a slightly +different syntax. The plugin will use only those queries, where the specified +minimum and maximum versions fit the version of the database in use. + +The database version is determined by C, see the +L +for details. Basically, each part of the version is assumed to be in the range +from B<00> to B<99> and all dots are removed. So version "4.1.2" becomes +"40102", version "5.0.42" becomes "50042". + +B The plugin will use B matching queries, so if you specify +multiple queries with the same name and B ranges, weird stuff will +happen. Don't to it! A valid example would be something along these lines: + + MinVersion 40000 + MaxVersion 49999 + ... + MinVersion 50000 + MaxVersion 50099 + ... + MinVersion 50100 + # No maximum + +In the above example, there are three ranges that don't overlap. The last one +goes from version "5.1.0" to infinity, meaning "all later versions". Versions +before "4.0.0" are not specified. + +=item B I + +The B that's used for each line returned. See L for more +details on how types are defined. In short: A type is a predefined layout of +data and the number of values and type of values has to match the type +definition. + +If you specify "temperature" here, you need exactly one gauge column. If you +specify "if_octets", you will need two counter columns. See the B +setting below. + +There must be exactly one B option inside each B block. + +=item B I + +Prepends I to the type instance. If B (see below) is not +given, the string is simply copied. If B is given, I and +all strings returned in the appropriate columns are concatenated together, +separated by dashes I<("-")>. + +=item B I [I ...] + +Specifies the columns whose values will be used to create the "type-instance" +for each row. If you specify more than one column, the value of all columns +will be join together with the dashes I<("-")> as separation character. + +The plugin itself does not check whether or not all built instances are +different. It's your responsibility to assure that each is unique. This is +especially true, if you do not specify B: B have to make +sure that only one row is returned in this case. + +If neither B nor B is given, the type-instance +will be empty. + +=item B I [I ...] + +Names the columns whose content is used as the actual data for the data sets +that are dispatched to the daemon. How many such columns you need is determined +by the B setting above. If you specify too many or not enough columns, +the plugin will complain about that and no data will be submitted to the +daemon. + +The actual data type in the columns is not that important. The plugin will +automatically cast the values to the right type if it know how to do that. So +it should be able to handle integer an floating point types, as well as strings +(if they include a number at the beginning). + +There must be at least one B option inside each B block. + +=back + +=head3 B blocks + +Database blocks define a connection to a database and which queries should be +sent to that database. Since the used "dbi" library can handle a wide variety +of databases, the configuration is very generic. If in doubt, refer to libdbi's +documentationE- we stick as close to the terminology used there. + +Each database needs a "name" as string argument in the starting tag of the +block. This name will be used as "PluginInstance" in the values submitted to +the daemon. Other than that, that name is not used. + +=over 4 + +=item B I + +Specifies the driver to use to connect to the database. In many cases those +drivers are named after the database they can connect to, but this is not a +technical necessity. These drivers are sometimes referred to as "DBD", +BataBase Briver, and some distributions ship them in separate +packages. Drivers for the "dbi" library are developed by the B +project at L. + +You need to give the driver name as expected by the "dbi" library here. You +should be able to find that in the documentation for each driver. If you +mistype the driver name, the plugin will dump a list of all known driver names +to the log. + +=item B I I + +Sets driver-specific options. What option a driver supports can be found in the +documentation for each driver, somewhere at +L. However, the options "host", +"username", "password", and "dbname" seem to be deEfacto standards. + +Unfortunately, drivers are not too keen to report errors when an unknown option +is passed to them, so invalid settings here may go unnoticed. This is not the +plugin's fault, it will report errors if it gets them from the libraryE/ +the driver. If a driver complains about an option, the plugin will dump a +complete list of all options understood by that driver to the log. + +=item B I + +In some cases, the database name you connect with is not the database name you +want to use for querying data. If this option is set, the plugin will "select" +(switch to) that database after the connection is established. + +=item B I + +Associates the query named I with this database connection. The +query needs to be defined I this statement, i.Ee. all query +blocks you want to refer to must be placed above the database block you want to +refer to them from. + +=back + =head2 Plugin C =over 4 @@ -491,6 +956,10 @@ description see above. Valid multipliers here are C (byte), C (kilobyte), C (megabyte), C (gigabyte), C (terabyte), and C

(petabyte). Please note that there are 1000 bytes in a kilobyte, not 1024. +=item B I|I + +Controls whether or not to recurse into subdirectories. Enabled by default. + =back =head2 Plugin C @@ -719,6 +1188,10 @@ Prefix all lines printed by the current time. Defaults to B. =back +B: There is no need to notify the daemon after moving or removing the +log file (e.Eg. when rotating the logs). The plugin reopens the file +for each line it writes. + =head2 Plugin C The C uses mbmon to retrieve temperature, voltage, etc. @@ -799,6 +1272,23 @@ Password needed to log into the database. Select this database. Defaults to I which is a perfectly reasonable option for what this plugin does. +=item B I + +TCP-port to connect to. The port must be specified in its numeric form, but it +must be passed as a string nonetheless. For example: + + Port "3306" + +If B is set to B (the default), this setting has no effect. +See the documentation for the C function for details. + +=item B I + +Specifies the path to the UNIX domain socket of the MySQL server. This option +only has any effect, if B is set to B (the default). +Otherwise, use the B option above. See the documentation for the +C function for details. + =back =head2 Plugin C @@ -1151,11 +1641,99 @@ controller, but as soon as you throw in a couple more senors and maybe a hub or two, reading all values will take more than ten seconds (the default interval). We will probably add some separate thread for reading the sensors and some cache or something like that, but it's not done yet. We will try to -maintain backwards compatibility in the future, but we can't probmise. So in -short: If it works for you: Great! But kaap in mind that the config I +maintain backwards compatibility in the future, but we can't promise. So in +short: If it works for you: Great! But keep in mind that the config I change, though this is unlikely. Oh, and if you want to help improving this plugin, just send a short notice to the mailing list. ThanksE:) +=head2 Plugin C + +The OpenVPN plugin reads a status file maintained by OpenVPN and gathers +traffic statistics about connected clients. + +To set up OpenVPN to write to the status file periodically, use the +B<--status> option of OpenVPN. Since OpenVPN can write two different formats, +you need to set the required format, too. This is done by setting +B<--status-version> to B<2>. + +So, in a nutshell you need: + + openvpn $OTHER_OPTIONS \ + --status "/var/run/openvpn-status" 10 \ + --status-version 2 + +Available options: + +=over 4 + +=item B I + +Specifies the location of the status file. + +=back + +=head2 Plugin C + +The "oracle" plugin uses the Oracle® Call Interface I<(OCI)> to connect to an +Oracle® Database and lets you execute SQL statements there. It is very similar +to the "dbi" plugin, because it was written around the same time. See the "dbi" +plugin's documentation above for details. + + + + Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category" + + Type "gauge" + # InstancePrefix "foo" + InstancesFrom "category" + ValuesFrom "value" + + + + ConnectID "db01" + Username "oracle" + Password "secret" + Query "out_of_stock" + + + +=head3 B blocks + +The Query blocks are handled identically to the Query blocks of the "dbi" +plugin. Please see its documentation above for details on how to specify +queries. + +=head3 B blocks + +Database blocks define a connection to a database and which queries should be +sent to that database. Each database needs a "name" as string argument in the +starting tag of the block. This name will be used as "PluginInstance" in the +values submitted to the daemon. Other than that, that name is not used. + +=over 4 + +=item B I + +Defines the "database alias" or "service name" to connect to. Usually, these +names are defined in the file named C<$ORACLE_HOME/network/admin/tnsnames.ora>. + +=item B I + +Username used for authentication. + +=item B I + +Password used for authentication. + +=item B I + +Associates the query named I with this database connection. The +query needs to be defined I this statement, i.Ee. all query +blocks you want to refer to must be placed above the database block you want to +refer to them from. + +=back + =head2 Plugin C This plugin embeds a Perl-interpreter into collectd and provides an interface @@ -1199,10 +1777,28 @@ L. - Query "SELECT magic, spells FROM wizard WHERE host = $1;" + Statement "SELECT magic FROM wizard WHERE host = $1;" Param hostname - Column gauge magic - Column counter spells + + Type gauge + InstancePrefix "magic" + ValuesFrom magic + + + + + Statement "SELECT COUNT(type) AS count, type \ + FROM (SELECT CASE \ + WHEN resolved = 'epoch' THEN 'open' \ + ELSE 'resolved' END AS type \ + FROM tickets) type \ + GROUP BY type;" + + Type counter + InstancePrefix "rt36_tickets" + InstancesFrom "type" + ValuesFrom "count" + @@ -1214,23 +1810,33 @@ L. KRBSrvName "kerberos_service_name" Query magic + Service "service_name" + Query backend # predefined + Query rt36_tickets The B block defines one database query which may later be used by a database definition. It accepts a single mandatory argument which specifies -the name of the query. The names of all queries have to be unique. The -following configuration options are available to define the query: +the name of the query. The names of all queries have to be unique (see the +B and B options below for an exception to this +rule). The following configuration options are available to define the query: + +In each B block, there is one or more B blocks. B +blocks define how to handle the values returned from the query. They define +which column holds which value and how to dispatch that value to the daemon. +Multiple B blocks may be used to extract multiple values from a single +query. =over 4 -=item B I +=item B I -Specify the I which the plugin should execute. The string may -contain the tokens B<$1>, B<$2>, etc. which are used to reference the first, -second, etc. parameter. The value of the parameters is specified by the +Specify the I which the plugin should execute. The string +may contain the tokens B<$1>, B<$2>, etc. which are used to reference the +first, second, etc. parameter. The value of the parameters is specified by the B configuration option - see below for details. To include a literal B<$> character followed by a number, surround it with single quotes (B<'>). @@ -1238,7 +1844,14 @@ Any SQL command which may return data (such as C