From: Florian Forster Date: Thu, 18 Jun 2015 14:52:09 +0000 (+0200) Subject: Merge branch 'collectd-5.4' into collectd-5.5 X-Git-Tag: collectd-5.5.1~98 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=0003c4d3c184f0f437499d6073cd023dc7b659c2;hp=-c;p=collectd.git Merge branch 'collectd-5.4' into collectd-5.5 --- 0003c4d3c184f0f437499d6073cd023dc7b659c2 diff --combined src/Makefile.am index 9839c03a,62f98751..c718621e --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -2,16 -2,12 +2,16 @@@ SUBDIRS = libcollectdclien if BUILD_WITH_OWN_LIBOCONFIG SUBDIRS += liboconfig endif +SUBDIRS += daemon + +PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\' if COMPILER_IS_GCC AM_CFLAGS = -Wall -Werror endif -AM_CPPFLAGS = -DPREFIX='"${prefix}"' +AM_CPPFLAGS = -I$(srcdir)/daemon +AM_CPPFLAGS += -DPREFIX='"${prefix}"' AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"' AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"' @@@ -21,24 -17,81 +21,24 @@@ endi AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"' AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"' -sbin_PROGRAMS = collectd collectdmon -bin_PROGRAMS = collectd-nagios collectdctl collectd-tg +AUTOMAKE_OPTIONS = subdir-objects -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_heap.c utils_heap.h \ - utils_ignorelist.c utils_ignorelist.h \ - utils_llist.c utils_llist.h \ - utils_parse_option.c utils_parse_option.h \ - utils_random.c utils_random.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_time.c utils_time.h \ - types_list.c types_list.h - -collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) -collectd_CFLAGS = $(AM_CFLAGS) -collectd_LDFLAGS = -export-dynamic -collectd_LDADD = -lm -collectd_DEPENDENCIES = - -# Link to these libraries.. -if BUILD_WITH_LIBRT -collectd_LDADD += -lrt -endif -if BUILD_WITH_LIBPOSIX4 -collectd_LDADD += -lposix4 -endif -if BUILD_WITH_LIBSOCKET -collectd_LDADD += -lsocket -endif -if BUILD_WITH_LIBRESOLV -collectd_LDADD += -lresolv -endif -if BUILD_WITH_LIBPTHREAD -collectd_LDADD += -lpthread -endif -if BUILD_WITH_LIBKSTAT -collectd_LDADD += -lkstat -endif -if BUILD_WITH_LIBDEVINFO -collectd_LDADD += -ldevinfo -endif -if BUILD_AIX -collectd_LDFLAGS += -Wl,-bexpall,-brtllib -endif +noinst_LTLIBRARIES = libmount.la liblookup.la -# The daemon needs to call sg_init, so we need to link it against libstatgrab, -# too. -octo -if BUILD_WITH_LIBSTATGRAB -collectd_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) -collectd_LDADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) -endif +libmount_la_SOURCES = utils_mount.c utils_mount.h +libmount_la_LIBADD = daemon/libcommon.la -if BUILD_WITH_OWN_LIBOCONFIG -collectd_LDADD += $(LIBLTDL) liboconfig/liboconfig.la -collectd_DEPENDENCIES += liboconfig/liboconfig.la -else -collectd_LDADD += -loconfig -endif +liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h +liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la + +sbin_PROGRAMS = collectdmon +bin_PROGRAMS = collectd-nagios collectdctl collectd-tg collectdmon_SOURCES = collectdmon.c collectdmon_CPPFLAGS = $(AM_CPPFLAGS) collectd_nagios_SOURCES = collectd-nagios.c -collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd +collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd collectd_nagios_LDADD = if BUILD_WITH_LIBSOCKET collectd_nagios_LDADD += -lsocket @@@ -52,7 -105,7 +52,7 @@@ collectd_nagios_DEPENDENCIES = libcolle collectdctl_SOURCES = collectdctl.c -collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd +collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd collectdctl_LDADD = if BUILD_WITH_LIBSOCKET collectdctl_LDADD += -lsocket @@@ -63,9 -116,10 +63,9 @@@ endi collectdctl_LDADD += libcollectdclient/libcollectdclient.la collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la -collectd_tg_SOURCES = collectd-tg.c \ - utils_heap.c utils_heap.h -collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd -collectd_tg_LDADD = +collectd_tg_SOURCES = collectd-tg.c +collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd +collectd_tg_LDADD = daemon/libheap.la if BUILD_WITH_LIBSOCKET collectd_tg_LDADD += -lsocket endif @@@ -75,24 -129,23 +75,24 @@@ endi if BUILD_AIX collectd_tg_LDADD += -lm endif +if BUILD_WITH_LIBPTHREAD +collectd_tg_LDADD += -lpthread +endif collectd_tg_LDADD += libcollectdclient/libcollectdclient.la collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la -pkglib_LTLIBRARIES = +pkglib_LTLIBRARIES = -BUILT_SOURCES = +BUILT_SOURCES = CLEANFILES = if BUILD_PLUGIN_AGGREGATION pkglib_LTLIBRARIES += aggregation.la aggregation_la_SOURCES = aggregation.c \ utils_vl_lookup.c utils_vl_lookup.h -aggregation_la_LDFLAGS = -module -avoid-version +aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS) aggregation_la_LIBADD = -lm -collectd_LDADD += "-dlopen" aggregation.la -collectd_DEPENDENCIES += aggregation.la endif if BUILD_PLUGIN_AMQP @@@ -101,122 -154,126 +101,122 @@@ amqp_la_SOURCES = amqp.c utils_cmd_putval.c utils_cmd_putval.h \ utils_format_graphite.c utils_format_graphite.h \ utils_format_json.c utils_format_json.h -amqp_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBRABBITMQ_LDFLAGS) +amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS) amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS) amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS) -collectd_LDADD += "-dlopen" amqp.la -collectd_DEPENDENCIES += amqp.la endif if BUILD_PLUGIN_APACHE pkglib_LTLIBRARIES += apache.la apache_la_SOURCES = apache.c -apache_la_LDFLAGS = -module -avoid-version +apache_la_LDFLAGS = $(PLUGIN_LDFLAGS) apache_la_CFLAGS = $(AM_CFLAGS) apache_la_LIBADD = -collectd_LDADD += "-dlopen" apache.la if BUILD_WITH_LIBCURL apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS) apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS) endif -collectd_DEPENDENCIES += apache.la endif if BUILD_PLUGIN_APCUPS pkglib_LTLIBRARIES += apcups.la apcups_la_SOURCES = apcups.c -apcups_la_LDFLAGS = -module -avoid-version +apcups_la_LDFLAGS = $(PLUGIN_LDFLAGS) apcups_la_LIBADD = if BUILD_WITH_LIBSOCKET apcups_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" apcups.la -collectd_DEPENDENCIES += apcups.la endif if BUILD_PLUGIN_APPLE_SENSORS pkglib_LTLIBRARIES += apple_sensors.la apple_sensors_la_SOURCES = apple_sensors.c -apple_sensors_la_LDFLAGS = -module -avoid-version +apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) apple_sensors_la_LDFLAGS += -framework IOKit -collectd_LDADD += "-dlopen" apple_sensors.la -collectd_DEPENDENCIES += apple_sensors.la endif if BUILD_PLUGIN_AQUAERO pkglib_LTLIBRARIES += aquaero.la aquaero_la_SOURCES = aquaero.c -aquaero_la_LDFLAGS = -module -avoid-version +aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS) aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS) aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5 -collectd_LDADD += "-dlopen" aquaero.la -collectd_DEPENDENCIES += aquaero.la endif if BUILD_PLUGIN_ASCENT pkglib_LTLIBRARIES += ascent.la ascent_la_SOURCES = ascent.c -ascent_la_LDFLAGS = -module -avoid-version +ascent_la_LDFLAGS = $(PLUGIN_LDFLAGS) ascent_la_CFLAGS = $(AM_CFLAGS) \ $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS) -collectd_LDADD += "-dlopen" ascent.la -collectd_DEPENDENCIES += ascent.la +endif + +if BUILD_PLUGIN_BAROMETER +pkglib_LTLIBRARIES += barometer.la +barometer_la_SOURCES = barometer.c +barometer_la_LDFLAGS = $(PLUGIN_LDFLAGS) +barometer_la_LIBADD = -lm endif if BUILD_PLUGIN_BATTERY pkglib_LTLIBRARIES += battery.la battery_la_SOURCES = battery.c -battery_la_LDFLAGS = -module -avoid-version +battery_la_LDFLAGS = $(PLUGIN_LDFLAGS) battery_la_LIBADD = if BUILD_WITH_LIBIOKIT battery_la_LDFLAGS += -framework IOKit endif -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_LDFLAGS = $(PLUGIN_LDFLAGS) bind_la_CFLAGS = $(AM_CFLAGS) \ - $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_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_CEPH +pkglib_LTLIBRARIES += ceph.la +ceph_la_SOURCES = ceph.c +ceph_la_CFLAGS = $(AM_CFLAGS) +ceph_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS) +ceph_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS) +ceph_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) endif if BUILD_PLUGIN_CGROUPS pkglib_LTLIBRARIES += cgroups.la -cgroups_la_SOURCES = cgroups.c utils_mount.c utils_mount.h -cgroups_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" cgroups.la -collectd_DEPENDENCIES += cgroups.la +cgroups_la_SOURCES = cgroups.c \ + utils_ignorelist.c utils_ignorelist.h +cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS) +cgroups_la_LIBADD = libmount.la endif if BUILD_PLUGIN_CONNTRACK pkglib_LTLIBRARIES += conntrack.la conntrack_la_SOURCES = conntrack.c -conntrack_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" conntrack.la -collectd_DEPENDENCIES += conntrack.la +conntrack_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_CONTEXTSWITCH pkglib_LTLIBRARIES += contextswitch.la contextswitch_la_SOURCES = contextswitch.c -contextswitch_la_LDFLAGS = -module -avoid-version +contextswitch_la_LDFLAGS = $(PLUGIN_LDFLAGS) contextswitch_la_LIBADD = if BUILD_WITH_PERFSTAT contextswitch_la_LIBADD += -lperfstat endif -collectd_LDADD += "-dlopen" contextswitch.la -collectd_DEPENDENCIES += contextswitch.la endif if BUILD_PLUGIN_CPU pkglib_LTLIBRARIES += cpu.la cpu_la_SOURCES = cpu.c cpu_la_CFLAGS = $(AM_CFLAGS) -cpu_la_LDFLAGS = -module -avoid-version -cpu_la_LIBADD = +cpu_la_LDFLAGS = $(PLUGIN_LDFLAGS) +cpu_la_LIBADD = if BUILD_WITH_LIBKSTAT cpu_la_LIBADD += -lkstat endif @@@ -230,52 -287,64 +230,52 @@@ endi if BUILD_WITH_PERFSTAT cpu_la_LIBADD += -lperfstat endif -collectd_LDADD += "-dlopen" cpu.la -collectd_DEPENDENCIES += cpu.la endif if BUILD_PLUGIN_CPUFREQ pkglib_LTLIBRARIES += cpufreq.la cpufreq_la_SOURCES = cpufreq.c -cpufreq_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" cpufreq.la -collectd_DEPENDENCIES += cpufreq.la +cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_CSV pkglib_LTLIBRARIES += csv.la csv_la_SOURCES = csv.c -csv_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" csv.la -collectd_DEPENDENCIES += csv.la +csv_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_CURL pkglib_LTLIBRARIES += curl.la curl_la_SOURCES = curl.c -curl_la_LDFLAGS = -module -avoid-version +curl_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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_CURL_JSON pkglib_LTLIBRARIES += curl_json.la curl_json_la_SOURCES = curl_json.c curl_json_la_CFLAGS = $(AM_CFLAGS) -curl_json_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS) -curl_json_la_CPPFLAGS = $(BUILD_WITH_LIBYAJL_CPPFLAGS) +curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS) +curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS) curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) if BUILD_WITH_LIBCURL curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS) curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS) endif -collectd_LDADD += "-dlopen" curl_json.la -collectd_DEPENDENCIES += curl_json.la endif if BUILD_PLUGIN_CURL_XML pkglib_LTLIBRARIES += curl_xml.la curl_xml_la_SOURCES = curl_xml.c -curl_xml_la_LDFLAGS = -module -avoid-version +curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS) curl_xml_la_CFLAGS = $(AM_CFLAGS) \ $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS) -collectd_LDADD += "-dlopen" curl_xml.la -collectd_DEPENDENCIES += curl_xml.la endif if BUILD_PLUGIN_DBI @@@ -283,25 -352,26 +283,25 @@@ pkglib_LTLIBRARIES += dbi.l 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_LDFLAGS = $(PLUGIN_LDFLAGS) $(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 -df_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" df.la -collectd_DEPENDENCIES += df.la +df_la_SOURCES = df.c \ + utils_ignorelist.c utils_ignorelist.h +df_la_LDFLAGS = $(PLUGIN_LDFLAGS) +df_la_LIBADD = libmount.la endif if BUILD_PLUGIN_DISK pkglib_LTLIBRARIES += disk.la -disk_la_SOURCES = disk.c +disk_la_SOURCES = disk.c \ + utils_ignorelist.c utils_ignorelist.h disk_la_CFLAGS = $(AM_CFLAGS) -disk_la_LDFLAGS = -module -avoid-version -disk_la_LIBADD = +disk_la_LDFLAGS = $(PLUGIN_LDFLAGS) +disk_la_LIBADD = if BUILD_WITH_LIBKSTAT disk_la_LIBADD += -lkstat endif @@@ -312,97 -382,99 +312,97 @@@ if BUILD_WITH_LIBIOKI disk_la_LDFLAGS += -framework IOKit endif if BUILD_WITH_LIBSTATGRAB -disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) +disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) disk_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) endif +if BUILD_WITH_LIBUDEV +disk_la_LIBADD += -ludev +endif if BUILD_WITH_PERFSTAT disk_la_LIBADD += -lperfstat endif -collectd_LDADD += "-dlopen" disk.la -collectd_DEPENDENCIES += disk.la endif if BUILD_PLUGIN_DNS pkglib_LTLIBRARIES += dns.la dns_la_SOURCES = dns.c utils_dns.c utils_dns.h -dns_la_LDFLAGS = -module -avoid-version +dns_la_LDFLAGS = $(PLUGIN_LDFLAGS) dns_la_LIBADD = -lpcap -lpthread -collectd_LDADD += "-dlopen" dns.la -collectd_DEPENDENCIES += dns.la +endif + +if BUILD_PLUGIN_DRBD +pkglib_LTLIBRARIES += drbd.la +drbd_la_SOURCES = drbd.c +drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS) +drbd_la_LIBADD = -lpthread endif if BUILD_PLUGIN_EMAIL pkglib_LTLIBRARIES += email.la email_la_SOURCES = email.c -email_la_LDFLAGS = -module -avoid-version +email_la_LDFLAGS = $(PLUGIN_LDFLAGS) email_la_LIBADD = -lpthread -collectd_LDADD += "-dlopen" email.la -collectd_DEPENDENCIES += email.la endif if BUILD_PLUGIN_ENTROPY pkglib_LTLIBRARIES += entropy.la entropy_la_SOURCES = entropy.c -entropy_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" entropy.la -collectd_DEPENDENCIES += entropy.la +entropy_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_EXEC pkglib_LTLIBRARIES += exec.la exec_la_SOURCES = exec.c \ utils_cmd_putnotif.c utils_cmd_putnotif.h \ - utils_cmd_putval.c utils_cmd_putval.h -exec_la_LDFLAGS = -module -avoid-version + utils_cmd_putval.c utils_cmd_putval.h \ + utils_parse_option.h utils_parse_option.c +exec_la_LDFLAGS = $(PLUGIN_LDFLAGS) exec_la_LIBADD = -lpthread -collectd_LDADD += "-dlopen" exec.la -collectd_DEPENDENCIES += exec.la endif if BUILD_PLUGIN_ETHSTAT pkglib_LTLIBRARIES += ethstat.la ethstat_la_SOURCES = ethstat.c -ethstat_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" ethstat.la -collectd_DEPENDENCIES += ethstat.la +ethstat_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + +if BUILD_PLUGIN_FHCOUNT +pkglib_LTLIBRARIES += fhcount.la +fhcount_la_SOURCES = fhcount.c +fhcount_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_FILECOUNT pkglib_LTLIBRARIES += filecount.la filecount_la_SOURCES = filecount.c -filecount_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" filecount.la -collectd_DEPENDENCIES += filecount.la +filecount_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_GMOND pkglib_LTLIBRARIES += gmond.la gmond_la_SOURCES = gmond.c gmond_la_CPPFLAGS = $(AM_CPPFLAGS) $(GANGLIA_CPPFLAGS) -gmond_la_LDFLAGS = -module -avoid-version $(GANGLIA_LDFLAGS) +gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS) gmond_la_LIBADD = $(GANGLIA_LIBS) -collectd_LDADD += "-dlopen" gmond.la -collectd_DEPENDENCIES += gmond.la endif if BUILD_PLUGIN_HDDTEMP pkglib_LTLIBRARIES += hddtemp.la hddtemp_la_SOURCES = hddtemp.c -hddtemp_la_LDFLAGS = -module -avoid-version +hddtemp_la_LDFLAGS = $(PLUGIN_LDFLAGS) hddtemp_la_LIBADD = if BUILD_WITH_LIBSOCKET hddtemp_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" hddtemp.la -collectd_DEPENDENCIES += hddtemp.la endif if BUILD_PLUGIN_INTERFACE pkglib_LTLIBRARIES += interface.la -interface_la_SOURCES = interface.c +interface_la_SOURCES = interface.c \ + utils_ignorelist.c utils_ignorelist.h interface_la_CFLAGS = $(AM_CFLAGS) -interface_la_LDFLAGS = -module -avoid-version +interface_la_LDFLAGS = $(PLUGIN_LDFLAGS) interface_la_LIBADD = -collectd_LDADD += "-dlopen" interface.la -collectd_DEPENDENCIES += interface.la if BUILD_WITH_LIBSTATGRAB interface_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) interface_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) @@@ -419,28 -491,24 +419,28 @@@ interface_la_LIBADD += -lperfsta endif endif # BUILD_PLUGIN_INTERFACE +if BUILD_PLUGIN_IPC +pkglib_LTLIBRARIES += ipc.la +ipc_la_SOURCES = ipc.c +ipc_la_CFLAGS = $(AM_CFLAGS) +ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + if BUILD_PLUGIN_IPTABLES pkglib_LTLIBRARIES += iptables.la iptables_la_SOURCES = iptables.c iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS) -iptables_la_LDFLAGS = -module -avoid-version +iptables_la_LDFLAGS = $(PLUGIN_LDFLAGS) iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS) -collectd_LDADD += "-dlopen" iptables.la -collectd_DEPENDENCIES += iptables.la endif if BUILD_PLUGIN_IPMI pkglib_LTLIBRARIES += ipmi.la -ipmi_la_SOURCES = ipmi.c +ipmi_la_SOURCES = ipmi.c \ + utils_ignorelist.c utils_ignorelist.h ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS) -ipmi_la_LDFLAGS = -module -avoid-version +ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS) ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS) -collectd_LDADD += "-dlopen" ipmi.la -collectd_DEPENDENCIES += ipmi.la endif if BUILD_PLUGIN_IPVS @@@ -449,14 -517,17 +449,14 @@@ ipvs_la_SOURCES = ipvs. if IP_VS_H_NEEDS_KERNEL_CFLAGS ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) endif -ipvs_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" ipvs.la -collectd_DEPENDENCIES += ipvs.la +ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_IRQ pkglib_LTLIBRARIES += irq.la -irq_la_SOURCES = irq.c -irq_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" irq.la -collectd_DEPENDENCIES += irq.la +irq_la_SOURCES = irq.c \ + utils_ignorelist.c utils_ignorelist.h +irq_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_JAVA @@@ -464,16 -535,31 +464,16 @@@ pkglib_LTLIBRARIES += java.l java_la_SOURCES = java.c java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS) java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS) -java_la_LDFLAGS = -module -avoid-version $(JAVA_LDFLAGS) +java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS) java_la_LIBADD = $(JAVA_LIBS) -collectd_LDADD += "-dlopen" java.la -collectd_DEPENDENCIES += java.la -endif - -if BUILD_PLUGIN_LIBVIRT -pkglib_LTLIBRARIES += libvirt.la -libvirt_la_SOURCES = libvirt.c -libvirt_la_CFLAGS = $(AM_CFLAGS) \ - $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) -libvirt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS) -libvirt_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" libvirt.la -collectd_DEPENDENCIES += libvirt.la endif if BUILD_PLUGIN_LOAD pkglib_LTLIBRARIES += load.la load_la_SOURCES = load.c load_la_CFLAGS = $(AM_CFLAGS) -load_la_LDFLAGS = -module -avoid-version +load_la_LDFLAGS = $(PLUGIN_LDFLAGS) load_la_LIBADD = -collectd_LDADD += "-dlopen" load.la -collectd_DEPENDENCIES += load.la if BUILD_WITH_LIBSTATGRAB load_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) load_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) @@@ -486,110 -572,127 +486,110 @@@ endif # BUILD_PLUGIN_LOA if BUILD_PLUGIN_LOGFILE pkglib_LTLIBRARIES += logfile.la logfile_la_SOURCES = logfile.c -logfile_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" logfile.la -collectd_DEPENDENCIES += logfile.la +logfile_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + +if BUILD_PLUGIN_LOG_LOGSTASH +pkglib_LTLIBRARIES += log_logstash.la +log_logstash_la_SOURCES = log_logstash.c +log_logstash_la_CFLAGS = $(AM_CFLAGS) +log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS) +log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS) +log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) endif if BUILD_PLUGIN_LPAR pkglib_LTLIBRARIES += lpar.la lpar_la_SOURCES = lpar.c -lpar_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" lpar.la -collectd_DEPENDENCIES += lpar.la +lpar_la_LDFLAGS = $(PLUGIN_LDFLAGS) lpar_la_LIBADD = -lperfstat endif if BUILD_PLUGIN_LVM pkglib_LTLIBRARIES += lvm.la lvm_la_SOURCES = lvm.c -lvm_la_LDFLAGS = -module -avoid-version +lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS) lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS) -collectd_LDADD += "-dlopen" lvm.la -collectd_DEPENDENCIES += lvm.la endif if BUILD_PLUGIN_MADWIFI pkglib_LTLIBRARIES += madwifi.la -madwifi_la_SOURCES = madwifi.c madwifi.h -madwifi_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" madwifi.la -collectd_DEPENDENCIES += madwifi.la +madwifi_la_SOURCES = madwifi.c madwifi.h \ + utils_ignorelist.c utils_ignorelist.h +madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_MATCH_EMPTY_COUNTER pkglib_LTLIBRARIES += match_empty_counter.la match_empty_counter_la_SOURCES = match_empty_counter.c -match_empty_counter_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" match_empty_counter.la -collectd_DEPENDENCIES += match_empty_counter.la +match_empty_counter_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_MATCH_HASHED pkglib_LTLIBRARIES += match_hashed.la match_hashed_la_SOURCES = match_hashed.c -match_hashed_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" match_hashed.la -collectd_DEPENDENCIES += match_hashed.la +match_hashed_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 +match_regex_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 +match_timediff_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 +match_value_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_MBMON pkglib_LTLIBRARIES += mbmon.la mbmon_la_SOURCES = mbmon.c -mbmon_la_LDFLAGS = -module -avoid-version +mbmon_la_LDFLAGS = $(PLUGIN_LDFLAGS) mbmon_la_LIBADD = if BUILD_WITH_LIBSOCKET mbmon_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" mbmon.la -collectd_DEPENDENCIES += mbmon.la endif if BUILD_PLUGIN_MD pkglib_LTLIBRARIES += md.la -md_la_SOURCES = md.c -md_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" md.la -collectd_DEPENDENCIES += md.la +md_la_SOURCES = md.c \ + utils_ignorelist.c utils_ignorelist.h +md_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_MEMCACHEC pkglib_LTLIBRARIES += memcachec.la memcachec_la_SOURCES = memcachec.c -memcachec_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBMEMCACHED_LDFLAGS) -memcachec_la_CPPFLAGS = $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS) +memcachec_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMEMCACHED_LDFLAGS) +memcachec_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS) memcachec_la_LIBADD = $(BUILD_WITH_LIBMEMCACHED_LIBS) -collectd_LDADD += "-dlopen" memcachec.la -collectd_DEPENDENCIES += memcachec.la endif if BUILD_PLUGIN_MEMCACHED pkglib_LTLIBRARIES += memcached.la memcached_la_SOURCES = memcached.c -memcached_la_LDFLAGS = -module -avoid-version +memcached_la_LDFLAGS = $(PLUGIN_LDFLAGS) memcached_la_LIBADD = if BUILD_WITH_LIBSOCKET memcached_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" memcached.la -collectd_DEPENDENCIES += memcached.la endif if BUILD_PLUGIN_MEMORY pkglib_LTLIBRARIES += memory.la memory_la_SOURCES = memory.c memory_la_CFLAGS = $(AM_CFLAGS) -memory_la_LDFLAGS = -module -avoid-version +memory_la_LDFLAGS = $(PLUGIN_LDFLAGS) memory_la_LIBADD = -collectd_LDADD += "-dlopen" memory.la -collectd_DEPENDENCIES += memory.la if BUILD_WITH_LIBKSTAT memory_la_LIBADD += -lkstat endif @@@ -605,56 -708,56 +605,56 @@@ memory_la_LIBADD += -lperfsta endif endif +if BUILD_PLUGIN_MIC +pkglib_LTLIBRARIES += mic.la +mic_la_SOURCES = mic.c \ + utils_ignorelist.c utils_ignorelist.h +mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH) +mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS) +mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD) +endif + if BUILD_PLUGIN_MODBUS pkglib_LTLIBRARIES += modbus.la modbus_la_SOURCES = modbus.c -modbus_la_LDFLAGS = -module -avoid-version +modbus_la_LDFLAGS = $(PLUGIN_LDFLAGS) modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS) modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS) -collectd_LDADD += "-dlopen" modbus.la -collectd_DEPENDENCIES += modbus.la endif if BUILD_PLUGIN_MULTIMETER pkglib_LTLIBRARIES += multimeter.la multimeter_la_SOURCES = multimeter.c -multimeter_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" multimeter.la -collectd_DEPENDENCIES += multimeter.la +multimeter_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_MYSQL pkglib_LTLIBRARIES += mysql.la mysql_la_SOURCES = mysql.c -mysql_la_LDFLAGS = -module -avoid-version +mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS) mysql_la_CFLAGS = $(AM_CFLAGS) mysql_la_LIBADD = -collectd_LDADD += "-dlopen" mysql.la if BUILD_WITH_LIBMYSQL mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS) mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS) endif -collectd_DEPENDENCIES += mysql.la endif if BUILD_PLUGIN_NETAPP pkglib_LTLIBRARIES += netapp.la -netapp_la_SOURCES = netapp.c +netapp_la_SOURCES = netapp.c \ + utils_ignorelist.c utils_ignorelist.h netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS) -netapp_la_LDFLAGS = -module -avoid-version $(LIBNETAPP_LDFLAGS) +netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS) netapp_la_LIBADD = $(LIBNETAPP_LIBS) -collectd_LDADD += "-dlopen" netapp.la -collectd_DEPENDENCIES += netapp.la endif if BUILD_PLUGIN_NETLINK pkglib_LTLIBRARIES += netlink.la netlink_la_SOURCES = netlink.c -netlink_la_LDFLAGS = -module -avoid-version +netlink_la_LDFLAGS = $(PLUGIN_LDFLAGS) netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS) netlink_la_LIBADD = $(BUILD_WITH_LIBMNL_LIBS) -collectd_LDADD += "-dlopen" netlink.la -collectd_DEPENDENCIES += netlink.la endif if BUILD_PLUGIN_NETWORK @@@ -662,7 -765,7 +662,7 @@@ pkglib_LTLIBRARIES += network.l network_la_SOURCES = network.c network.h \ utils_fbhash.c utils_fbhash.h network_la_CPPFLAGS = $(AM_CPPFLAGS) -network_la_LDFLAGS = -module -avoid-version +network_la_LDFLAGS = $(PLUGIN_LDFLAGS) network_la_LIBADD = -lpthread if BUILD_WITH_LIBSOCKET network_la_LIBADD += -lsocket @@@ -672,18 -775,24 +672,18 @@@ network_la_CPPFLAGS += $(GCRYPT_CPPFLAG network_la_LDFLAGS += $(GCRYPT_LDFLAGS) network_la_LIBADD += $(GCRYPT_LIBS) endif -collectd_LDADD += "-dlopen" network.la -collectd_DEPENDENCIES += network.la endif if BUILD_PLUGIN_NFS pkglib_LTLIBRARIES += nfs.la nfs_la_SOURCES = nfs.c -nfs_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" nfs.la -collectd_DEPENDENCIES += nfs.la +nfs_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_FSCACHE pkglib_LTLIBRARIES += fscache.la fscache_la_SOURCES = fscache.c -fscache_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" fscache.la -collectd_DEPENDENCIES += fscache.la +fscache_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_NGINX @@@ -691,85 -800,94 +691,85 @@@ pkglib_LTLIBRARIES += nginx.l nginx_la_SOURCES = nginx.c nginx_la_CFLAGS = $(AM_CFLAGS) nginx_la_LIBADD = -nginx_la_LDFLAGS = -module -avoid-version +nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS) if BUILD_WITH_LIBCURL nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS) nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS) endif -collectd_LDADD += "-dlopen" nginx.la -collectd_DEPENDENCIES += nginx.la endif if BUILD_PLUGIN_NOTIFY_DESKTOP pkglib_LTLIBRARIES += notify_desktop.la notify_desktop_la_SOURCES = notify_desktop.c notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS) -notify_desktop_la_LDFLAGS = -module -avoid-version +notify_desktop_la_LDFLAGS = $(PLUGIN_LDFLAGS) notify_desktop_la_LIBADD = $(LIBNOTIFY_LIBS) -collectd_LDADD += "-dlopen" notify_desktop.la -collectd_DEPENDENCIES += notify_desktop.la endif if BUILD_PLUGIN_NOTIFY_EMAIL pkglib_LTLIBRARIES += notify_email.la notify_email_la_SOURCES = notify_email.c -notify_email_la_LDFLAGS = -module -avoid-version +notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS) notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread -collectd_LDADD += "-dlopen" notify_email.la -collectd_DEPENDENCIES += notify_email.la endif if BUILD_PLUGIN_NTPD pkglib_LTLIBRARIES += ntpd.la ntpd_la_SOURCES = ntpd.c -ntpd_la_LDFLAGS = -module -avoid-version +ntpd_la_LDFLAGS = $(PLUGIN_LDFLAGS) ntpd_la_LIBADD = if BUILD_WITH_LIBSOCKET ntpd_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" ntpd.la -collectd_DEPENDENCIES += ntpd.la endif if BUILD_PLUGIN_NUMA pkglib_LTLIBRARIES += numa.la numa_la_SOURCES = numa.c -numa_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" numa.la -collectd_DEPENDENCIES += numa.la +numa_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_NUT pkglib_LTLIBRARIES += nut.la nut_la_SOURCES = nut.c nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS) -nut_la_LDFLAGS = -module -avoid-version +nut_la_LDFLAGS = $(PLUGIN_LDFLAGS) nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS) -collectd_LDADD += "-dlopen" nut.la -collectd_DEPENDENCIES += nut.la endif if BUILD_PLUGIN_OLSRD pkglib_LTLIBRARIES += olsrd.la olsrd_la_SOURCES = olsrd.c -olsrd_la_LDFLAGS = -module -avoid-version -olsrd_la_LIBADD = +olsrd_la_LDFLAGS = $(PLUGIN_LDFLAGS) +olsrd_la_LIBADD = if BUILD_WITH_LIBSOCKET olsrd_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" olsrd.la -collectd_DEPENDENCIES += olsrd.la endif if BUILD_PLUGIN_ONEWIRE pkglib_LTLIBRARIES += onewire.la -onewire_la_SOURCES = onewire.c +onewire_la_SOURCES = onewire.c \ + utils_ignorelist.c utils_ignorelist.h onewire_la_CFLAGS = $(AM_CFLAGS) -onewire_la_CPPFLAGS = $(BUILD_WITH_LIBOWCAPI_CPPFLAGS) +onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS) onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS) -onewire_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" onewire.la -collectd_DEPENDENCIES += onewire.la +onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + +if BUILD_PLUGIN_OPENLDAP +pkglib_LTLIBRARIES += openldap.la +openldap_la_SOURCES = openldap.c +openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS) +openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS) +openldap_la_LIBADD = -lldap 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 +openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_ORACLE @@@ -777,9 -895,11 +777,9 @@@ pkglib_LTLIBRARIES += oracle.l 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_CPPFLAGS = $(AM_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 +oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_PERL @@@ -796,31 -916,39 +796,31 @@@ perl_la_CFLAGS = $(AM_CFLAGS) if HAVE_BROKEN_PERL_LOAD_MODULE perl_la_CFLAGS += -Wno-nonnull endif -perl_la_LDFLAGS = -module -avoid-version \ +perl_la_LDFLAGS = $(PLUGIN_LDFLAGS) \ $(PERL_LDFLAGS) perl_la_LIBADD = $(PERL_LIBS) -collectd_LDADD += "-dlopen" perl.la -collectd_DEPENDENCIES += perl.la endif if BUILD_PLUGIN_PF pkglib_LTLIBRARIES += pf.la pf_la_SOURCES = pf.c -pf_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" pf.la -collectd_DEPENDENCIES += pf.la +pf_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_PINBA pkglib_LTLIBRARIES += pinba.la pinba_la_SOURCES = pinba.c nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h -pinba_la_LDFLAGS = -module -avoid-version +pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS) pinba_la_LIBADD = -lprotobuf-c -collectd_LDADD += "-dlopen" pinba.la -collectd_DEPENDENCIES += pinba.la endif if BUILD_PLUGIN_PING pkglib_LTLIBRARIES += ping.la ping_la_SOURCES = ping.c ping_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOPING_CPPFLAGS) -ping_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBOPING_LDFLAGS) +ping_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOPING_LDFLAGS) ping_la_LIBADD = -loping -lm -collectd_LDADD += "-dlopen" ping.la -collectd_DEPENDENCIES += ping.la endif if BUILD_PLUGIN_POSTGRESQL @@@ -828,15 -956,19 +828,15 @@@ pkglib_LTLIBRARIES += postgresql.l 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 \ +postgresql_la_LDFLAGS = $(PLUGIN_LDFLAGS) \ $(BUILD_WITH_LIBPQ_LDFLAGS) postgresql_la_LIBADD = -lpq -collectd_LDADD += "-dlopen" postgresql.la -collectd_DEPENDENCIES += postgresql.la endif if BUILD_PLUGIN_POWERDNS pkglib_LTLIBRARIES += powerdns.la powerdns_la_SOURCES = powerdns.c -powerdns_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" powerdns.la -collectd_DEPENDENCIES += powerdns.la +powerdns_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_PYTHON @@@ -847,15 -979,19 +847,15 @@@ python_la_CFLAGS = $(AM_CFLAGS if COMPILER_IS_GCC python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing endif -python_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_PYTHON_LDFLAGS) +python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS) python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS) -collectd_LDADD += "-dlopen" python.la -collectd_DEPENDENCIES += python.la endif if BUILD_PLUGIN_PROCESSES pkglib_LTLIBRARIES += processes.la processes_la_SOURCES = processes.c -processes_la_LDFLAGS = -module -avoid-version +processes_la_LDFLAGS = $(PLUGIN_LDFLAGS) processes_la_LIBADD = -collectd_LDADD += "-dlopen" processes.la -collectd_DEPENDENCIES += processes.la if BUILD_WITH_LIBKVM_GETPROCS processes_la_LIBADD += -lkvm endif @@@ -863,81 -999,84 +863,81 @@@ endi if BUILD_PLUGIN_PROTOCOLS pkglib_LTLIBRARIES += protocols.la -protocols_la_SOURCES = protocols.c -protocols_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" protocols.la -collectd_DEPENDENCIES += protocols.la +protocols_la_SOURCES = protocols.c \ + utils_ignorelist.c utils_ignorelist.h +protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_REDIS pkglib_LTLIBRARIES += redis.la redis_la_SOURCES = redis.c -redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS) -redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS) -redis_la_LIBADD = -lcredis -collectd_LDADD += "-dlopen" redis.la -collectd_DEPENDENCIES += redis.la +redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS) +redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS) +redis_la_LIBADD = -lhiredis endif if BUILD_PLUGIN_ROUTEROS pkglib_LTLIBRARIES += routeros.la routeros_la_SOURCES = routeros.c -routeros_la_CPPFLAGS = $(BUILD_WITH_LIBROUTEROS_CPPFLAGS) -routeros_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBROUTEROS_LDFLAGS) +routeros_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBROUTEROS_CPPFLAGS) +routeros_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBROUTEROS_LDFLAGS) routeros_la_LIBADD = -lrouteros -collectd_LDADD += "-dlopen" routeros.la -collectd_DEPENDENCIES += routeros.la 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_LDFLAGS = $(PLUGIN_LDFLAGS) 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 utils_rrdcreate.c utils_rrdcreate.h -rrdtool_la_LDFLAGS = -module -avoid-version +rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS) rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS) rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS) -collectd_LDADD += "-dlopen" rrdtool.la -collectd_DEPENDENCIES += rrdtool.la endif if BUILD_PLUGIN_SENSORS pkglib_LTLIBRARIES += sensors.la -sensors_la_SOURCES = sensors.c +sensors_la_SOURCES = sensors.c \ + utils_ignorelist.c utils_ignorelist.h sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS) -sensors_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSENSORS_LDFLAGS) +sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS) sensors_la_LIBADD = -lsensors -collectd_LDADD += "-dlopen" sensors.la -collectd_DEPENDENCIES += sensors.la endif if BUILD_PLUGIN_SERIAL pkglib_LTLIBRARIES += serial.la serial_la_SOURCES = serial.c -serial_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" serial.la -collectd_DEPENDENCIES += serial.la +serial_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_SIGROK pkglib_LTLIBRARIES += sigrok.la sigrok_la_SOURCES = sigrok.c sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS) -sigrok_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSIGROK_LDFLAGS) +sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS) sigrok_la_LIBADD = -lsigrok -collectd_LDADD += "-dlopen" sigrok.la -collectd_DEPENDENCIES += sigrok.la +endif + +if BUILD_PLUGIN_SMART +if BUILD_WITH_LIBUDEV +pkglib_LTLIBRARIES += smart.la +smart_la_SOURCES = smart.c \ + utils_ignorelist.c utils_ignorelist.h +smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS) +smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS) +smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev +endif endif if BUILD_PLUGIN_SNMP pkglib_LTLIBRARIES += snmp.la snmp_la_SOURCES = snmp.c -snmp_la_LDFLAGS = -module -avoid-version +snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS) snmp_la_CFLAGS = $(AM_CFLAGS) snmp_la_LIBADD = if BUILD_WITH_LIBNETSNMP @@@ -947,22 -1086,28 +947,22 @@@ endi if BUILD_WITH_LIBPTHREAD snmp_la_LIBADD += -lpthread endif -collectd_LDADD += "-dlopen" snmp.la -collectd_DEPENDENCIES += snmp.la endif if BUILD_PLUGIN_STATSD pkglib_LTLIBRARIES += statsd.la statsd_la_SOURCES = statsd.c \ utils_latency.h utils_latency.c -statsd_la_LDFLAGS = -module -avoid-version +statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS) - statsd_la_LIBADD = -lpthread + statsd_la_LIBADD = -lpthread -lm -collectd_LDADD += "-dlopen" statsd.la -collectd_DEPENDENCIES += statsd.la endif if BUILD_PLUGIN_SWAP pkglib_LTLIBRARIES += swap.la swap_la_SOURCES = swap.c swap_la_CFLAGS = $(AM_CFLAGS) -swap_la_LDFLAGS = -module -avoid-version +swap_la_LDFLAGS = $(PLUGIN_LDFLAGS) swap_la_LIBADD = -collectd_LDADD += "-dlopen" swap.la -collectd_DEPENDENCIES += swap.la if BUILD_WITH_LIBKSTAT swap_la_LIBADD += -lkstat endif @@@ -985,69 -1130,91 +985,69 @@@ endi if BUILD_PLUGIN_SYSLOG pkglib_LTLIBRARIES += syslog.la syslog_la_SOURCES = syslog.c -syslog_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" syslog.la -collectd_DEPENDENCIES += syslog.la +syslog_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TABLE pkglib_LTLIBRARIES += table.la table_la_SOURCES = table.c -table_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" table.la -collectd_DEPENDENCIES += table.la +table_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TAIL pkglib_LTLIBRARIES += tail.la tail_la_SOURCES = tail.c -tail_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" tail.la -collectd_DEPENDENCIES += tail.la +tail_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TAIL_CSV pkglib_LTLIBRARIES += tail_csv.la tail_csv_la_SOURCES = tail_csv.c -tail_csv_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" tail_csv.la -collectd_DEPENDENCIES += tail_csv.la +tail_csv_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TAPE pkglib_LTLIBRARIES += tape.la tape_la_SOURCES = tape.c -tape_la_LDFLAGS = -module -avoid-version +tape_la_LDFLAGS = $(PLUGIN_LDFLAGS) tape_la_LIBADD = -lkstat -ldevinfo -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 +target_notification_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 +target_replace_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TARGET_SCALE pkglib_LTLIBRARIES += target_scale.la target_scale_la_SOURCES = target_scale.c -target_scale_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" target_scale.la -collectd_DEPENDENCIES += target_scale.la +target_scale_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 +target_set_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TARGET_V5UPGRADE pkglib_LTLIBRARIES += target_v5upgrade.la target_v5upgrade_la_SOURCES = target_v5upgrade.c -target_v5upgrade_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" target_v5upgrade.la -collectd_DEPENDENCIES += target_v5upgrade.la +target_v5upgrade_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TCPCONNS pkglib_LTLIBRARIES += tcpconns.la tcpconns_la_SOURCES = tcpconns.c -tcpconns_la_LDFLAGS = -module -avoid-version +tcpconns_la_LDFLAGS = $(PLUGIN_LDFLAGS) tcpconns_la_LIBADD = -collectd_LDADD += "-dlopen" tcpconns.la -collectd_DEPENDENCIES += tcpconns.la if BUILD_WITH_LIBKVM_NLIST tcpconns_la_LIBADD += -lkvm endif @@@ -1056,43 -1223,46 +1056,43 @@@ endi if BUILD_PLUGIN_TEAMSPEAK2 pkglib_LTLIBRARIES += teamspeak2.la teamspeak2_la_SOURCES = teamspeak2.c -teamspeak2_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" teamspeak2.la -collectd_DEPENDENCIES += teamspeak2.la +teamspeak2_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TED pkglib_LTLIBRARIES += ted.la ted_la_SOURCES = ted.c -ted_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" ted.la -collectd_DEPENDENCIES += ted.la +ted_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_THERMAL pkglib_LTLIBRARIES += thermal.la -thermal_la_SOURCES = thermal.c -thermal_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" thermal.la -collectd_DEPENDENCIES += thermal.la +thermal_la_SOURCES = thermal.c \ + utils_ignorelist.c utils_ignorelist.h +thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_THRESHOLD pkglib_LTLIBRARIES += threshold.la threshold_la_SOURCES = threshold.c -threshold_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" threshold.la -collectd_DEPENDENCIES += threshold.la +threshold_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_TOKYOTYRANT pkglib_LTLIBRARIES += tokyotyrant.la tokyotyrant_la_SOURCES = tokyotyrant.c tokyotyrant_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS) -tokyotyrant_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS) +tokyotyrant_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS) tokyotyrant_la_LIBADD = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS) if BUILD_WITH_LIBSOCKET tokyotyrant_la_LIBADD += -lsocket endif -collectd_LDADD += "-dlopen" tokyotyrant.la -collectd_DEPENDENCIES += tokyotyrant.la +endif + +if BUILD_PLUGIN_TURBOSTAT +pkglib_LTLIBRARIES += turbostat.la +turbostat_la_SOURCES = turbostat.c +turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_UNIXSOCK @@@ -1100,20 -1270,20 +1100,20 @@@ pkglib_LTLIBRARIES += unixsock.l unixsock_la_SOURCES = unixsock.c \ utils_cmd_flush.h utils_cmd_flush.c \ utils_cmd_getval.h utils_cmd_getval.c \ + utils_cmd_getthreshold.h utils_cmd_getthreshold.c \ utils_cmd_listval.h utils_cmd_listval.c \ utils_cmd_putval.h utils_cmd_putval.c \ - utils_cmd_putnotif.h utils_cmd_putnotif.c -unixsock_la_LDFLAGS = -module -avoid-version + utils_cmd_putnotif.h utils_cmd_putnotif.c \ + utils_parse_option.h utils_parse_option.c +unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS) unixsock_la_LIBADD = -lpthread -collectd_LDADD += "-dlopen" unixsock.la -collectd_DEPENDENCIES += unixsock.la endif if BUILD_PLUGIN_UPTIME pkglib_LTLIBRARIES += uptime.la uptime_la_SOURCES = uptime.c uptime_la_CFLAGS = $(AM_CFLAGS) -uptime_la_LDFLAGS = -module -avoid-version +uptime_la_LDFLAGS = $(PLUGIN_LDFLAGS) uptime_la_LIBADD = if BUILD_WITH_LIBKSTAT uptime_la_LIBADD += -lkstat @@@ -1121,18 -1291,22 +1121,18 @@@ endi if BUILD_WITH_PERFSTAT uptime_la_LIBADD += -lperfstat endif -collectd_LDADD += "-dlopen" uptime.la -collectd_DEPENDENCIES += uptime.la endif if BUILD_PLUGIN_USERS pkglib_LTLIBRARIES += users.la users_la_SOURCES = users.c users_la_CFLAGS = $(AM_CFLAGS) -users_la_LDFLAGS = -module -avoid-version +users_la_LDFLAGS = $(PLUGIN_LDFLAGS) users_la_LIBADD = if BUILD_WITH_LIBSTATGRAB users_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) users_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) endif -collectd_LDADD += "-dlopen" users.la -collectd_DEPENDENCIES += users.la endif if BUILD_PLUGIN_UUID @@@ -1140,43 -1314,53 +1140,43 @@@ pkglib_LTLIBRARIES += uuid.l uuid_la_SOURCES = uuid.c uuid_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHAL_CFLAGS) uuid_la_LIBADD = $(BUILD_WITH_LIBHAL_LIBS) -uuid_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" uuid.la -collectd_DEPENDENCIES += uuid.la -endif - -if BUILD_PLUGIN_MIC -pkglib_LTLIBRARIES += mic.la -mic_la_SOURCES = mic.c -mic_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_MIC_LIBPATH) -mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS) -mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD) -collectd_LDADD += "-dlopen" mic.la -collectd_DEPENDENCIES += mic.la +uuid_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_VARNISH pkglib_LTLIBRARIES += varnish.la varnish_la_SOURCES = varnish.c -varnish_la_LDFLAGS = -module -avoid-version +varnish_la_LDFLAGS = $(PLUGIN_LDFLAGS) varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS) varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS) -collectd_LDADD += "-dlopen" varnish.la -collectd_DEPENDENCIES += varnish.la +endif + +if BUILD_PLUGIN_VIRT +pkglib_LTLIBRARIES += virt.la +virt_la_SOURCES = virt.c \ + utils_ignorelist.c utils_ignorelist.h +virt_la_CFLAGS = $(AM_CFLAGS) \ + $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) +virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS) +virt_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_VMEM pkglib_LTLIBRARIES += vmem.la vmem_la_SOURCES = vmem.c -vmem_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" vmem.la -collectd_DEPENDENCIES += vmem.la +vmem_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_VSERVER pkglib_LTLIBRARIES += vserver.la vserver_la_SOURCES = vserver.c -vserver_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" vserver.la -collectd_DEPENDENCIES += vserver.la +vserver_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_WIRELESS pkglib_LTLIBRARIES += wireless.la wireless_la_SOURCES = wireless.c -wireless_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" wireless.la -collectd_DEPENDENCIES += wireless.la +wireless_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_WRITE_GRAPHITE @@@ -1184,106 -1368,78 +1184,106 @@@ pkglib_LTLIBRARIES += write_graphite.l write_graphite_la_SOURCES = write_graphite.c \ utils_format_graphite.c utils_format_graphite.h \ utils_format_json.c utils_format_json.h -write_graphite_la_LDFLAGS = -module -avoid-version -collectd_LDADD += "-dlopen" write_graphite.la -collectd_DEPENDENCIES += write_graphite.la +write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_WRITE_HTTP pkglib_LTLIBRARIES += write_http.la write_http_la_SOURCES = write_http.c \ utils_format_json.c utils_format_json.h -write_http_la_LDFLAGS = -module -avoid-version +write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS) write_http_la_CFLAGS = $(AM_CFLAGS) write_http_la_LIBADD = -collectd_LDADD += "-dlopen" write_http.la if BUILD_WITH_LIBCURL write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS) write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS) endif -collectd_DEPENDENCIES += write_http.la +endif + +if BUILD_PLUGIN_WRITE_KAFKA +pkglib_LTLIBRARIES += write_kafka.la +write_kafka_la_SOURCES = write_kafka.c \ + utils_format_graphite.c utils_format_graphite.h \ + utils_format_json.c utils_format_json.h \ + utils_cmd_putval.c utils_cmd_putval.h \ + utils_crc32.c utils_crc32.h +write_kafka_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRDKAFKA_CPPFLAGS) +write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS) +write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS) +endif + +if BUILD_PLUGIN_WRITE_LOG +pkglib_LTLIBRARIES += write_log.la +write_log_la_SOURCES = write_log.c \ + utils_format_graphite.c utils_format_graphite.h +write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_WRITE_MONGODB pkglib_LTLIBRARIES += write_mongodb.la write_mongodb_la_SOURCES = write_mongodb.c write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS) -write_mongodb_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBMONGOC_LDFLAGS) +write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS) write_mongodb_la_LIBADD = -lmongoc -collectd_LDADD += "-dlopen" write_mongodb.la -collectd_DEPENDENCIES += write_mongodb.la endif if BUILD_PLUGIN_WRITE_REDIS pkglib_LTLIBRARIES += write_redis.la write_redis_la_SOURCES = write_redis.c -write_redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS) -write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS) -write_redis_la_LIBADD = -lcredis -collectd_LDADD += "-dlopen" write_redis.la -collectd_DEPENDENCIES += write_redis.la +write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS) +write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS) +write_redis_la_LIBADD = -lhiredis endif if BUILD_PLUGIN_WRITE_RIEMANN pkglib_LTLIBRARIES += write_riemann.la -write_riemann_la_SOURCES = write_riemann.c +write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h -write_riemann_la_LDFLAGS = -module -avoid-version +write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS) write_riemann_la_LIBADD = -lprotobuf-c -collectd_LDADD += "-dlopen" write_riemann.la -collectd_DEPENDENCIES += write_riemann.la +endif + +if BUILD_PLUGIN_WRITE_SENSU +pkglib_LTLIBRARIES += write_sensu.la +write_sensu_la_SOURCES = write_sensu.c +write_sensu_la_LDFLAGS = $(PLUGIN_LDFLAGS) +endif + +if BUILD_PLUGIN_WRITE_TSDB +pkglib_LTLIBRARIES += write_tsdb.la +write_tsdb_la_SOURCES = write_tsdb.c +write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif if BUILD_PLUGIN_XMMS pkglib_LTLIBRARIES += xmms.la xmms_la_SOURCES = xmms.c xmms_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBXMMS_CFLAGS) -xmms_la_LDFLAGS = -module -avoid-version +xmms_la_LDFLAGS = $(PLUGIN_LDFLAGS) xmms_la_LIBADD = $(BUILD_WITH_LIBXMMS_LIBS) -collectd_LDADD += "-dlopen" xmms.la -collectd_DEPENDENCIES += xmms.la endif if BUILD_PLUGIN_ZFS_ARC pkglib_LTLIBRARIES += zfs_arc.la zfs_arc_la_SOURCES = zfs_arc.c zfs_arc_la_CFLAGS = $(AM_CFLAGS) -zfs_arc_la_LDFLAGS = -module -avoid-version +zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS) if BUILD_FREEBSD zfs_arc_la_LIBADD = -lm else +if BUILD_LINUX +# zfs_arc requires no library on linux +else +# solaris zfs_arc_la_LIBADD = -lkstat endif -collectd_LDADD += "-dlopen" zfs_arc.la -collectd_DEPENDENCIES += zfs_arc.la +endif +endif + +if BUILD_PLUGIN_ZOOKEEPER +pkglib_LTLIBRARIES += zookeeper.la +zookeeper_la_SOURCES = zookeeper.c +zookeeper_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif BUILT_SOURCES += $(dist_man_MANS) @@@ -1380,12 -1536,15 +1380,12 @@@ uninstall-hook rm -f $(DESTDIR)$(sysconfdir)/collectd.conf rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf; -if BUILD_FEATURE_DEBUG -bin_PROGRAMS += utils_vl_lookup_test -utils_vl_lookup_test_SOURCES = utils_vl_lookup_test.c \ - utils_vl_lookup.h utils_vl_lookup.c \ - utils_avltree.c utils_avltree.h \ - common.h +check_PROGRAMS = test_utils_mount test_utils_vl_lookup -utils_vl_lookup_test_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) -DBUILD_TEST=1 -utils_vl_lookup_test_CFLAGS = $(AM_CFLAGS) -utils_vl_lookup_test_LDFLAGS = -export-dynamic -utils_vl_lookup_test_LDADD = -endif +test_utils_mount_SOURCES = utils_mount_test.c testing.h +test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la + +test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h +test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la + +TESTS = test_utils_mount test_utils_vl_lookup diff --combined src/daemon/collectd.c index a708665d,00000000..46e13b3f mode 100644,000000..100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@@ -1,718 -1,0 +1,719 @@@ +/** + * collectd - src/collectd.c + * Copyright (C) 2005-2007 Florian octo Forster + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Florian octo Forster + * Alvaro Barcellos + **/ + +#include "collectd.h" +#include "common.h" + +#include "plugin.h" +#include "configfile.h" + +#include +#include +#include +#include + +#include + +#if HAVE_LOCALE_H +# include +#endif + +#if HAVE_STATGRAB_H +# include +#endif + +#ifndef COLLECTD_LOCALE +# define COLLECTD_LOCALE "C" +#endif + +/* + * Global variables + */ +char hostname_g[DATA_MAX_NAME_LEN]; +cdtime_t interval_g; +int pidfile_from_cli = 0; +int timeout_g; +#if HAVE_LIBKSTAT +kstat_ctl_t *kc; +#endif /* HAVE_LIBKSTAT */ + +static int loop = 0; + +static void *do_flush (void __attribute__((unused)) *arg) +{ + INFO ("Flushing all data."); + plugin_flush (/* plugin = */ NULL, + /* timeout = */ 0, + /* ident = */ NULL); + INFO ("Finished flushing all data."); + pthread_exit (NULL); + return NULL; +} + +static void sig_int_handler (int __attribute__((unused)) signal) +{ + loop++; +} + +static void sig_term_handler (int __attribute__((unused)) signal) +{ + loop++; +} + +static void sig_usr1_handler (int __attribute__((unused)) signal) +{ + pthread_t thread; + pthread_attr_t attr; + + /* flushing the data might take a while, + * so it should be done asynchronously */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pthread_create (&thread, &attr, do_flush, NULL); + pthread_attr_destroy (&attr); +} + +static int init_hostname (void) +{ + const char *str; + + struct addrinfo ai_hints; + struct addrinfo *ai_list; + struct addrinfo *ai_ptr; + int status; + + str = global_option_get ("Hostname"); + if (str != NULL) + { + sstrncpy (hostname_g, str, sizeof (hostname_g)); + return (0); + } + + if (gethostname (hostname_g, sizeof (hostname_g)) != 0) + { + fprintf (stderr, "`gethostname' failed and no " + "hostname was configured.\n"); + return (-1); + } + + str = global_option_get ("FQDNLookup"); + if (IS_FALSE (str)) + return (0); + + memset (&ai_hints, '\0', sizeof (ai_hints)); + ai_hints.ai_flags = AI_CANONNAME; + + status = getaddrinfo (hostname_g, NULL, &ai_hints, &ai_list); + if (status != 0) + { + ERROR ("Looking up \"%s\" failed. You have set the " + "\"FQDNLookup\" option, but I cannot resolve " + "my hostname to a fully qualified domain " + "name. Please fix the network " + "configuration.", hostname_g); + return (-1); + } + + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + { + if (ai_ptr->ai_canonname == NULL) + continue; + + sstrncpy (hostname_g, ai_ptr->ai_canonname, sizeof (hostname_g)); + break; + } + + freeaddrinfo (ai_list); + return (0); +} /* int init_hostname */ + +static int init_global_variables (void) +{ + char const *str; + + interval_g = cf_get_default_interval (); + assert (interval_g > 0); + DEBUG ("interval_g = %.3f;", CDTIME_T_TO_DOUBLE (interval_g)); + + str = global_option_get ("Timeout"); + if (str == NULL) + str = "2"; + timeout_g = atoi (str); + if (timeout_g <= 1) + { + fprintf (stderr, "Cannot set the timeout to a correct value.\n" + "Please check your settings.\n"); + return (-1); + } + DEBUG ("timeout_g = %i;", timeout_g); + + if (init_hostname () != 0) + return (-1); + DEBUG ("hostname_g = %s;", hostname_g); + + return (0); +} /* int init_global_variables */ + +static int change_basedir (const char *orig_dir) +{ + char *dir; + size_t dirlen; + int status; + + dir = strdup (orig_dir); + if (dir == NULL) + { + char errbuf[1024]; + ERROR ("strdup failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + dirlen = strlen (dir); + while ((dirlen > 0) && (dir[dirlen - 1] == '/')) + dir[--dirlen] = '\0'; + + if (dirlen <= 0) + return (-1); + + status = chdir (dir); + if (status == 0) + { + free (dir); + return (0); + } + else if (errno != ENOENT) + { + char errbuf[1024]; + ERROR ("change_basedir: chdir (%s): %s", dir, + sstrerror (errno, errbuf, sizeof (errbuf))); + free (dir); + return (-1); + } + + status = mkdir (dir, S_IRWXU | S_IRWXG | S_IRWXO); + if (status != 0) + { + char errbuf[1024]; + ERROR ("change_basedir: mkdir (%s): %s", dir, + sstrerror (errno, errbuf, sizeof (errbuf))); + free (dir); + return (-1); + } + + status = chdir (dir); + if (status != 0) + { + char errbuf[1024]; + ERROR ("change_basedir: chdir (%s): %s", dir, + sstrerror (errno, errbuf, sizeof (errbuf))); + free (dir); + return (-1); + } + + free (dir); + return (0); +} /* static int change_basedir (char *dir) */ + +#if HAVE_LIBKSTAT +static void update_kstat (void) +{ + if (kc == NULL) + { + if ((kc = kstat_open ()) == NULL) + ERROR ("Unable to open kstat control structure"); + } + else + { + kid_t kid; + kid = kstat_chain_update (kc); + if (kid > 0) + { + INFO ("kstat chain has been updated"); + plugin_init_all (); + } + else if (kid < 0) + ERROR ("kstat chain update failed"); + /* else: everything works as expected */ + } + + return; +} /* static void update_kstat (void) */ +#endif /* HAVE_LIBKSTAT */ + +/* TODO + * Remove all settings but `-f' and `-C' + */ +static void exit_usage (int status) +{ + printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n" + + "Available options:\n" + " General:\n" + " -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 + " -f Don't fork to the background.\n" +#endif + " -h Display help (this message)\n" + "\nBuiltin defaults:\n" + " Config file "CONFIGFILE"\n" + " PID file "PIDFILE"\n" + " Plugin directory "PLUGINDIR"\n" + " Data directory "PKGLOCALSTATEDIR"\n" + "\n"PACKAGE_NAME" "PACKAGE_VERSION", http://collectd.org/\n" + "by Florian octo Forster \n" + "for contributions see `AUTHORS'\n"); + exit (status); +} /* static void exit_usage (int status) */ + +static int do_init (void) +{ +#if HAVE_SETLOCALE + if (setlocale (LC_NUMERIC, COLLECTD_LOCALE) == NULL) + WARNING ("setlocale (\"%s\") failed.", COLLECTD_LOCALE); +#endif + +#if HAVE_LIBKSTAT + kc = NULL; + update_kstat (); +#endif + +#if HAVE_LIBSTATGRAB + if (sg_init ( +# if HAVE_LIBSTATGRAB_0_90 + 0 +# endif + )) + { + ERROR ("sg_init: %s", sg_str_error (sg_get_error ())); + return (-1); + } + + if (sg_drop_privileges ()) + { + ERROR ("sg_drop_privileges: %s", sg_str_error (sg_get_error ())); + return (-1); + } +#endif + + plugin_init_all (); + + return (0); +} /* int do_init () */ + + +static int do_loop (void) +{ + cdtime_t interval = cf_get_default_interval (); + cdtime_t wait_until; + + wait_until = cdtime () + interval; + + while (loop == 0) + { + struct timespec ts_wait = { 0, 0 }; + cdtime_t now; + +#if HAVE_LIBKSTAT + update_kstat (); +#endif + + /* Issue all plugins */ + plugin_read_all (); + + now = cdtime (); + if (now >= wait_until) + { + WARNING ("Not sleeping because the next interval is " + "%.3f seconds in the past!", + CDTIME_T_TO_DOUBLE (now - wait_until)); + wait_until = now + interval; + continue; + } + + CDTIME_T_TO_TIMESPEC (wait_until - now, &ts_wait); + wait_until = wait_until + interval; + + while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) != 0)) + { + if (errno != EINTR) + { + char errbuf[1024]; + ERROR ("nanosleep failed: %s", + sstrerror (errno, errbuf, + sizeof (errbuf))); + return (-1); + } + } + } /* while (loop == 0) */ + + return (0); +} /* int do_loop */ + +static int do_shutdown (void) +{ + plugin_shutdown_all (); + return (0); +} /* int do_shutdown */ + +#if COLLECT_DAEMON +static int pidfile_create (void) +{ + FILE *fh; + const char *file = global_option_get ("PIDFile"); + + if ((fh = fopen (file, "w")) == NULL) + { + char errbuf[1024]; + ERROR ("fopen (%s): %s", file, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (1); + } + + fprintf (fh, "%i\n", (int) getpid ()); + fclose(fh); + + return (0); +} /* static int pidfile_create (const char *file) */ + +static int pidfile_remove (void) +{ + const char *file = global_option_get ("PIDFile"); ++ if (file == NULL) ++ return 0; + - DEBUG ("unlink (%s)", (file != NULL) ? file : ""); + return (unlink (file)); +} /* static int pidfile_remove (const char *file) */ +#endif /* COLLECT_DAEMON */ + +#ifdef KERNEL_LINUX +int notify_upstart (void) +{ + const char *upstart_job = getenv("UPSTART_JOB"); + + if (upstart_job == NULL) + return 0; + + if (strcmp(upstart_job, "collectd") != 0) + return 0; + + WARNING ("supervised by upstart, will stop to signal readyness"); + raise(SIGSTOP); + unsetenv("UPSTART_JOB"); + + return 1; +} + +int notify_systemd (void) +{ + int fd = -1; + const char *notifysocket = getenv("NOTIFY_SOCKET"); + struct sockaddr_un su; + struct iovec iov; + struct msghdr hdr; + + if (notifysocket == NULL) + return 0; + + if ((strchr("@/", notifysocket[0])) == NULL || + strlen(notifysocket) < 2) + return 0; + + WARNING ("supervised by systemd, will signal readyness"); + if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + WARNING ("cannot contact systemd socket %s", notifysocket); + return 0; + } + + bzero(&su, sizeof(su)); + su.sun_family = AF_UNIX; + sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path)); + + if (notifysocket[0] == '@') + su.sun_path[0] = 0; + + bzero(&iov, sizeof(iov)); + iov.iov_base = "READY=1"; + iov.iov_len = strlen("READY=1"); + + bzero(&hdr, sizeof(hdr)); + hdr.msg_name = &su; + hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + + strlen(notifysocket); + hdr.msg_iov = &iov; + hdr.msg_iovlen = 1; + + unsetenv("NOTIFY_SOCKET"); + if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) { + WARNING ("cannot send notification to systemd"); + close(fd); + return 0; + } + close(fd); + return 1; +} +#endif /* KERNEL_LINUX */ + +int main (int argc, char **argv) +{ + struct sigaction sig_int_action; + struct sigaction sig_term_action; + struct sigaction sig_usr1_action; + 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, "htTC:" +#if COLLECT_DAEMON + "fP:" +#endif + ); + + if (c == -1) + break; + + switch (c) + { + case 'C': + configfile = optarg; + break; + 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); + pidfile_from_cli = 1; + break; + case 'f': + daemonize = 0; + break; +#endif /* COLLECT_DAEMON */ + case 'h': + exit_usage (0); + break; + default: + exit_usage (1); + } /* switch (c) */ + } /* while (1) */ + + if (optind < argc) + exit_usage (1); + + plugin_init_ctx (); + + /* + * Read options from the config file, the environment and the command + * line (in that order, with later options overwriting previous ones in + * general). + * Also, this will automatically load modules. + */ + if (cf_read (configfile)) + { + fprintf (stderr, "Error: Reading the config file failed!\n" + "Read the syslog for details.\n"); + return (1); + } + + /* + * Change directory. We do this _after_ reading the config and loading + * modules to relative paths work as expected. + */ + if ((basedir = global_option_get ("BaseDir")) == NULL) + { + fprintf (stderr, "Don't have a basedir to use. This should not happen. Ever."); + return (1); + } + else if (change_basedir (basedir)) + { + fprintf (stderr, "Error: Unable to change to directory `%s'.\n", basedir); + return (1); + } + + /* + * Set global variables or, if that failes, exit. We cannot run with + * them being uninitialized. If nothing is configured, then defaults + * are being used. So this means that the user has actually done + * something wrong. + */ + if (init_global_variables () != 0) + return (1); + + if (test_config) + return (0); + +#if COLLECT_DAEMON + /* + * fork off child + */ + memset (&sig_chld_action, '\0', sizeof (sig_chld_action)); + sig_chld_action.sa_handler = SIG_IGN; + sigaction (SIGCHLD, &sig_chld_action, NULL); + + /* + * Only daemonize if we're not being supervised + * by upstart or systemd (when using Linux). + */ + if (daemonize +#ifdef KERNEL_LINUX + && notify_upstart() == 0 && notify_systemd() == 0 +#endif + ) + { + if ((pid = fork ()) == -1) + { + /* error */ + char errbuf[1024]; + fprintf (stderr, "fork: %s", + sstrerror (errno, errbuf, + sizeof (errbuf))); + return (1); + } + else if (pid != 0) + { + /* parent */ + /* printf ("Running (PID %i)\n", pid); */ + return (0); + } + + /* Detach from session */ + setsid (); + + /* Write pidfile */ + if (pidfile_create ()) + exit (2); + + /* close standard descriptors */ + close (2); + close (1); + close (0); + + if (open ("/dev/null", O_RDWR) != 0) + { + ERROR ("Error: Could not connect `STDIN' to `/dev/null'"); + return (1); + } + if (dup (0) != 1) + { + ERROR ("Error: Could not connect `STDOUT' to `/dev/null'"); + return (1); + } + if (dup (0) != 2) + { + ERROR ("Error: Could not connect `STDERR' to `/dev/null'"); + return (1); + } + } /* if (daemonize) */ +#endif /* COLLECT_DAEMON */ + + memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action)); + sig_pipe_action.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sig_pipe_action, NULL); + + /* + * install signal handlers + */ + memset (&sig_int_action, '\0', sizeof (sig_int_action)); + sig_int_action.sa_handler = sig_int_handler; + if (0 != sigaction (SIGINT, &sig_int_action, NULL)) { + char errbuf[1024]; + ERROR ("Error: Failed to install a signal handler for signal INT: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (1); + } + + memset (&sig_term_action, '\0', sizeof (sig_term_action)); + sig_term_action.sa_handler = sig_term_handler; + if (0 != sigaction (SIGTERM, &sig_term_action, NULL)) { + char errbuf[1024]; + ERROR ("Error: Failed to install a signal handler for signal TERM: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (1); + } + + memset (&sig_usr1_action, '\0', sizeof (sig_usr1_action)); + sig_usr1_action.sa_handler = sig_usr1_handler; + if (0 != sigaction (SIGUSR1, &sig_usr1_action, NULL)) { + char errbuf[1024]; + ERROR ("Error: Failed to install a signal handler for signal USR1: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (1); + } + + /* + * run the actual loops + */ + do_init (); + + 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."); + + do_shutdown (); + +#if COLLECT_DAEMON + if (daemonize) + pidfile_remove (); +#endif /* COLLECT_DAEMON */ + + return (exit_status); +} /* int main */ diff --combined src/daemon/configfile.c index 765a23c4,00000000..8fc6f7d7 mode 100644,000000..100644 --- a/src/daemon/configfile.c +++ b/src/daemon/configfile.c @@@ -1,1365 -1,0 +1,1369 @@@ +/** + * collectd - src/configfile.c + * Copyright (C) 2005-2011 Florian octo Forster + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Florian octo Forster + * Sebastian tokkee Harl + **/ + +#include "collectd.h" + +#include "liboconfig/oconfig.h" + +#include "common.h" +#include "plugin.h" +#include "configfile.h" +#include "types_list.h" +#include "filter_chain.h" + +#if HAVE_WORDEXP_H +# include +#endif /* HAVE_WORDEXP_H */ + +#if HAVE_FNMATCH_H +# include +#endif /* HAVE_FNMATCH_H */ + +#if HAVE_LIBGEN_H +# include +#endif /* HAVE_LIBGEN_H */ + +#define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str)) + +/* + * Private types + */ +typedef struct cf_callback +{ + const char *type; + int (*callback) (const char *, const char *); + const char **keys; + int keys_num; + plugin_ctx_t ctx; + struct cf_callback *next; +} cf_callback_t; + +typedef struct cf_complex_callback_s +{ + char *type; + int (*callback) (oconfig_item_t *); + plugin_ctx_t ctx; + struct cf_complex_callback_s *next; +} cf_complex_callback_t; + +typedef struct cf_value_map_s +{ + char *key; + int (*func) (oconfig_item_t *); +} cf_value_map_t; + +typedef struct cf_global_option_s +{ + char *key; + char *value; + char *def; +} cf_global_option_t; + +/* + * Prototypes of callback functions + */ +static int dispatch_value_typesdb (oconfig_item_t *ci); +static int dispatch_value_plugindir (oconfig_item_t *ci); +static int dispatch_loadplugin (oconfig_item_t *ci); +static int dispatch_block_plugin (oconfig_item_t *ci); + +/* + * Private variables + */ +static cf_callback_t *first_callback = NULL; +static cf_complex_callback_t *complex_callback_head = NULL; + +static cf_value_map_t cf_value_map[] = +{ + {"TypesDB", dispatch_value_typesdb}, + {"PluginDir", dispatch_value_plugindir}, + {"LoadPlugin", dispatch_loadplugin}, + {"Plugin", dispatch_block_plugin} +}; +static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map); + +static cf_global_option_t cf_global_options[] = +{ + {"BaseDir", NULL, PKGLOCALSTATEDIR}, + {"PIDFile", NULL, PIDFILE}, + {"Hostname", NULL, NULL}, + {"FQDNLookup", NULL, "true"}, + {"Interval", NULL, NULL}, + {"ReadThreads", NULL, "5"}, + {"WriteThreads", NULL, "5"}, + {"WriteQueueLimitHigh", NULL, NULL}, + {"WriteQueueLimitLow", NULL, NULL}, + {"Timeout", NULL, "2"}, + {"AutoLoadPlugin", NULL, "false"}, + {"CollectInternalStats", NULL, "false"}, + {"PreCacheChain", NULL, "PreCache"}, + {"PostCacheChain", NULL, "PostCache"}, + {"MaxReadInterval", NULL, "86400"} +}; +static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options); + +static int cf_default_typesdb = 1; + +/* + * Functions to handle register/unregister, search, and other plugin related + * stuff + */ +static cf_callback_t *cf_search (const char *type) +{ + cf_callback_t *cf_cb; + + if (type == NULL) + return (NULL); + + for (cf_cb = first_callback; cf_cb != NULL; cf_cb = cf_cb->next) + if (strcasecmp (cf_cb->type, type) == 0) + break; + + return (cf_cb); +} + +static int cf_dispatch (const char *type, const char *orig_key, + const char *orig_value) +{ + cf_callback_t *cf_cb; + plugin_ctx_t old_ctx; + char *key; + char *value; + int ret; + int i; + ++ if (orig_key == NULL) ++ return (EINVAL); ++ + DEBUG ("type = %s, key = %s, value = %s", + ESCAPE_NULL(type), - ESCAPE_NULL(orig_key), ++ orig_key, + ESCAPE_NULL(orig_value)); + + if ((cf_cb = cf_search (type)) == NULL) + { + WARNING ("Found a configuration for the `%s' plugin, but " + "the plugin isn't loaded or didn't register " + "a configuration callback.", type); + return (-1); + } + + if ((key = strdup (orig_key)) == NULL) + return (1); + if ((value = strdup (orig_value)) == NULL) + { + free (key); + return (2); + } + + ret = -1; + + old_ctx = plugin_set_ctx (cf_cb->ctx); + + for (i = 0; i < cf_cb->keys_num; i++) + { + if ((cf_cb->keys[i] != NULL) + && (strcasecmp (cf_cb->keys[i], key) == 0)) + { + ret = (*cf_cb->callback) (key, value); + break; + } + } + + plugin_set_ctx (old_ctx); + + if (i >= cf_cb->keys_num) + WARNING ("Plugin `%s' did not register for value `%s'.", type, key); + + free (key); + free (value); + - DEBUG ("cf_dispatch: return (%i)", ret); - + return (ret); +} /* int cf_dispatch */ + +static int dispatch_global_option (const oconfig_item_t *ci) +{ + if (ci->values_num != 1) + return (-1); + if (ci->values[0].type == OCONFIG_TYPE_STRING) + return (global_option_set (ci->key, ci->values[0].value.string)); + else if (ci->values[0].type == OCONFIG_TYPE_NUMBER) + { + char tmp[128]; + ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number); + return (global_option_set (ci->key, tmp)); + } + else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN) + { + if (ci->values[0].value.boolean) + return (global_option_set (ci->key, "true")); + else + return (global_option_set (ci->key, "false")); + } + + return (-1); +} /* int dispatch_global_option */ + +static int dispatch_value_typesdb (oconfig_item_t *ci) +{ + int i = 0; + + assert (strcasecmp (ci->key, "TypesDB") == 0); + + cf_default_typesdb = 0; + + if (ci->values_num < 1) { + ERROR ("configfile: `TypesDB' needs at least one argument."); + return (-1); + } + + for (i = 0; i < ci->values_num; ++i) + { + if (OCONFIG_TYPE_STRING != ci->values[i].type) { + WARNING ("configfile: TypesDB: Skipping %i. argument which " + "is not a string.", i + 1); + continue; + } + + read_types_list (ci->values[i].value.string); + } + return (0); +} /* int dispatch_value_typesdb */ + +static int dispatch_value_plugindir (oconfig_item_t *ci) +{ + assert (strcasecmp (ci->key, "PluginDir") == 0); + + if (ci->values_num != 1) + return (-1); + if (ci->values[0].type != OCONFIG_TYPE_STRING) + return (-1); + + plugin_set_dir (ci->values[0].value.string); + return (0); +} + +static int dispatch_loadplugin (oconfig_item_t *ci) +{ + int i; + const char *name; + unsigned int flags = 0; + plugin_ctx_t ctx; + plugin_ctx_t old_ctx; + int ret_val; + + assert (strcasecmp (ci->key, "LoadPlugin") == 0); + + if (ci->values_num != 1) + return (-1); + if (ci->values[0].type != OCONFIG_TYPE_STRING) + return (-1); + + name = ci->values[0].value.string; + if (strcmp ("libvirt", name) == 0) + name = "virt"; + + /* default to the global interval set before loading this plugin */ + memset (&ctx, 0, sizeof (ctx)); + ctx.interval = cf_get_default_interval (); + + for (i = 0; i < ci->children_num; ++i) { + if (strcasecmp("Globals", ci->children[i].key) == 0) + cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL); + else if (strcasecmp ("Interval", ci->children[i].key) == 0) { + if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) { + /* cf_util_get_cdtime will log an error */ + continue; + } + } + else { + WARNING("Ignoring unknown LoadPlugin option \"%s\" " + "for plugin \"%s\"", + ci->children[i].key, ci->values[0].value.string); + } + } + + old_ctx = plugin_set_ctx (ctx); + ret_val = plugin_load (name, (uint32_t) flags); + /* reset to the "global" context */ + plugin_set_ctx (old_ctx); + + return (ret_val); +} /* int dispatch_value_loadplugin */ + +static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci) +{ + char buffer[4096]; + char *buffer_ptr; + int buffer_free; + int i; + + buffer_ptr = buffer; + buffer_free = sizeof (buffer); + + for (i = 0; i < ci->values_num; i++) + { + int status = -1; + + if (ci->values[i].type == OCONFIG_TYPE_STRING) + status = ssnprintf (buffer_ptr, buffer_free, " %s", + ci->values[i].value.string); + else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) + status = ssnprintf (buffer_ptr, buffer_free, " %lf", + ci->values[i].value.number); + else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) + status = ssnprintf (buffer_ptr, buffer_free, " %s", + ci->values[i].value.boolean + ? "true" : "false"); + + if ((status < 0) || (status >= buffer_free)) + return (-1); + buffer_free -= status; + buffer_ptr += status; + } + /* skip the initial space */ + buffer_ptr = buffer + 1; + + return (cf_dispatch (plugin, ci->key, buffer_ptr)); +} /* int dispatch_value_plugin */ + +static int dispatch_value (oconfig_item_t *ci) +{ + int ret = -2; + int i; + + for (i = 0; i < cf_value_map_num; i++) + if (strcasecmp (cf_value_map[i].key, ci->key) == 0) + { + ret = cf_value_map[i].func (ci); + break; + } + + for (i = 0; i < cf_global_options_num; i++) + if (strcasecmp (cf_global_options[i].key, ci->key) == 0) + { + ret = dispatch_global_option (ci); + break; + } + + return (ret); +} /* int dispatch_value */ + +static int dispatch_block_plugin (oconfig_item_t *ci) +{ + int i; + char *name; + + cf_complex_callback_t *cb; + + if (strcasecmp (ci->key, "Plugin") != 0) + return (-1); + if (ci->values_num < 1) + return (-1); + if (ci->values[0].type != OCONFIG_TYPE_STRING) + return (-1); + + name = ci->values[0].value.string; + if (strcmp ("libvirt", name) == 0) + { + /* TODO(octo): Remove this legacy. */ + WARNING ("The \"libvirt\" plugin has been renamed to \"virt\" to avoid problems with the build system. " + "Your configuration is still using the old name. " + "Please change it to use \"virt\" as soon as possible. " + "This compatibility code will go away eventually."); + name = "virt"; + } + + if (IS_TRUE (global_option_get ("AutoLoadPlugin"))) + { + plugin_ctx_t ctx; + plugin_ctx_t old_ctx; + int status; + + /* default to the global interval set before loading this plugin */ + memset (&ctx, 0, sizeof (ctx)); + ctx.interval = cf_get_default_interval (); + + old_ctx = plugin_set_ctx (ctx); + status = plugin_load (name, /* flags = */ 0); + /* reset to the "global" context */ + plugin_set_ctx (old_ctx); + + if (status != 0) + { + ERROR ("Automatically loading plugin \"%s\" failed " + "with status %i.", name, status); + return (status); + } + } + + /* Check for a complex callback first */ + for (cb = complex_callback_head; cb != NULL; cb = cb->next) + { + if (strcasecmp (name, cb->type) == 0) + { + plugin_ctx_t old_ctx; + int ret_val; + + old_ctx = plugin_set_ctx (cb->ctx); + ret_val = (cb->callback (ci)); + plugin_set_ctx (old_ctx); + return (ret_val); + } + } + + /* Hm, no complex plugin found. Dispatch the values one by one */ + for (i = 0; i < ci->children_num; i++) + { + if (ci->children[i].children == NULL) + dispatch_value_plugin (name, ci->children + i); + else + { + WARNING ("There is a `%s' block within the " + "configuration for the %s plugin. " + "The plugin either only expects " + "\"simple\" configuration statements " + "or wasn't loaded using `LoadPlugin'." + " Please check your configuration.", + ci->children[i].key, name); + } + } + + return (0); +} + + +static int dispatch_block (oconfig_item_t *ci) +{ + if (strcasecmp (ci->key, "LoadPlugin") == 0) + return (dispatch_loadplugin (ci)); + else if (strcasecmp (ci->key, "Plugin") == 0) + return (dispatch_block_plugin (ci)); + else if (strcasecmp (ci->key, "Chain") == 0) + return (fc_configure (ci)); + + return (0); +} + +static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src, + int offset) +{ + oconfig_item_t *temp; + int i; + + assert (offset >= 0); + assert (dst->children_num > offset); + + /* Free the memory used by the replaced child. Usually that's the + * `Include "blah"' statement. */ + temp = dst->children + offset; + for (i = 0; i < temp->values_num; i++) + { + if (temp->values[i].type == OCONFIG_TYPE_STRING) + { + sfree (temp->values[i].value.string); + } + } + sfree (temp->values); + temp = NULL; + + /* If (src->children_num == 0) the array size is decreased. If offset + * is _not_ the last element, (offset < (dst->children_num - 1)), then + * we need to move the trailing elements before resizing the array. */ + if ((src->children_num == 0) && (offset < (dst->children_num - 1))) + { + int nmemb = dst->children_num - (offset + 1); + memmove (dst->children + offset, dst->children + offset + 1, + sizeof (oconfig_item_t) * nmemb); + } + + /* Resize the memory containing the children to be big enough to hold + * all children. */ + if (dst->children_num + src->children_num - 1 == 0) + { + dst->children_num = 0; + return (0); + } + + temp = (oconfig_item_t *) realloc (dst->children, + sizeof (oconfig_item_t) + * (dst->children_num + src->children_num - 1)); + if (temp == NULL) + { + ERROR ("configfile: realloc failed."); + return (-1); + } + dst->children = temp; + + /* If there are children behind the include statement, and they have + * not yet been moved because (src->children_num == 0), then move them + * to the end of the list, so that the new children have room before + * them. */ + if ((src->children_num > 0) + && ((dst->children_num - (offset + 1)) > 0)) + { + int nmemb = dst->children_num - (offset + 1); + int old_offset = offset + 1; + int new_offset = offset + src->children_num; + + memmove (dst->children + new_offset, + dst->children + old_offset, + sizeof (oconfig_item_t) * nmemb); + } + + /* Last but not least: If there are new children, copy them to the + * memory reserved for them. */ + if (src->children_num > 0) + { + memcpy (dst->children + offset, + src->children, + sizeof (oconfig_item_t) * src->children_num); + } + + /* Update the number of children. */ + dst->children_num += (src->children_num - 1); + + return (0); +} /* int cf_ci_replace_child */ + +static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src) +{ + oconfig_item_t *temp; + + if ((src == NULL) || (src->children_num == 0)) + return (0); + + temp = (oconfig_item_t *) realloc (dst->children, + sizeof (oconfig_item_t) + * (dst->children_num + src->children_num)); + if (temp == NULL) + { + ERROR ("configfile: realloc failed."); + return (-1); + } + dst->children = temp; + + memcpy (dst->children + dst->children_num, + src->children, + sizeof (oconfig_item_t) + * src->children_num); + dst->children_num += src->children_num; + + return (0); +} /* int cf_ci_append_children */ + +#define CF_MAX_DEPTH 8 +static oconfig_item_t *cf_read_generic (const char *path, + const char *pattern, int depth); + +static int cf_include_all (oconfig_item_t *root, int depth) +{ + int i; + + for (i = 0; i < root->children_num; i++) + { + oconfig_item_t *new; + oconfig_item_t *old; + + char *pattern = NULL; + + int j; + + if (strcasecmp (root->children[i].key, "Include") != 0) + continue; + + old = root->children + i; + + if ((old->values_num != 1) + || (old->values[0].type != OCONFIG_TYPE_STRING)) + { + ERROR ("configfile: `Include' needs exactly one string argument."); + continue; + } + + for (j = 0; j < old->children_num; ++j) + { + oconfig_item_t *child = old->children + j; + + if (strcasecmp (child->key, "Filter") == 0) + cf_util_get_string (child, &pattern); + else + ERROR ("configfile: Option `%s' not allowed in block.", + child->key); + } + + new = cf_read_generic (old->values[0].value.string, pattern, depth + 1); + sfree (pattern); + + if (new == NULL) + return (-1); + + /* Now replace the i'th child in `root' with `new'. */ + if (cf_ci_replace_child (root, new, i) < 0) + return (-1); + + /* ... and go back to the new i'th child. */ + --i; + + sfree (new->values); + sfree (new); + } /* for (i = 0; i < root->children_num; i++) */ + + return (0); +} /* int cf_include_all */ + +static oconfig_item_t *cf_read_file (const char *file, + const char *pattern, int depth) +{ + oconfig_item_t *root; + int status; + + assert (depth < CF_MAX_DEPTH); + + if (pattern != NULL) { +#if HAVE_FNMATCH_H && HAVE_LIBGEN_H + char *tmp = sstrdup (file); + char *filename = basename (tmp); + + if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) { + DEBUG ("configfile: Not including `%s' because it " + "does not match pattern `%s'.", + filename, pattern); + free (tmp); + return (NULL); + } + + free (tmp); +#else + ERROR ("configfile: Cannot apply pattern filter '%s' " + "to file '%s': functions basename() and / or " + "fnmatch() not available.", pattern, file); +#endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */ + } + + root = oconfig_parse_file (file); + if (root == NULL) + { + ERROR ("configfile: Cannot read file `%s'.", file); + return (NULL); + } + + status = cf_include_all (root, depth); + if (status != 0) + { + oconfig_free (root); + return (NULL); + } + + return (root); +} /* oconfig_item_t *cf_read_file */ + +static int cf_compare_string (const void *p1, const void *p2) +{ + return strcmp (*(const char **) p1, *(const char **) p2); +} + +static oconfig_item_t *cf_read_dir (const char *dir, + const char *pattern, int depth) +{ + oconfig_item_t *root = NULL; + DIR *dh; + struct dirent *de; + char **filenames = NULL; + int filenames_num = 0; + int status; + int i; + + assert (depth < CF_MAX_DEPTH); + + dh = opendir (dir); + if (dh == NULL) + { + char errbuf[1024]; + ERROR ("configfile: opendir failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (NULL); + } + + root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t)); + if (root == NULL) + { + ERROR ("configfile: malloc failed."); + return (NULL); + } + memset (root, 0, sizeof (oconfig_item_t)); + + while ((de = readdir (dh)) != NULL) + { + char name[1024]; + char **tmp; + + if ((de->d_name[0] == '.') || (de->d_name[0] == 0)) + continue; + + status = ssnprintf (name, sizeof (name), "%s/%s", + dir, de->d_name); + if ((status < 0) || ((size_t) status >= sizeof (name))) + { + ERROR ("configfile: Not including `%s/%s' because its" + " name is too long.", + dir, de->d_name); + for (i = 0; i < filenames_num; ++i) + free (filenames[i]); + free (filenames); + free (root); + return (NULL); + } + + ++filenames_num; + tmp = (char **) realloc (filenames, + filenames_num * sizeof (*filenames)); + if (tmp == NULL) { + ERROR ("configfile: realloc failed."); + for (i = 0; i < filenames_num - 1; ++i) + free (filenames[i]); + free (filenames); + free (root); + return (NULL); + } + filenames = tmp; + + filenames[filenames_num - 1] = sstrdup (name); + } + ++ if (filenames == NULL) ++ return (root); ++ + qsort ((void *) filenames, filenames_num, sizeof (*filenames), + cf_compare_string); + + for (i = 0; i < filenames_num; ++i) + { + oconfig_item_t *temp; + char *name = filenames[i]; + + temp = cf_read_generic (name, pattern, depth); + if (temp == NULL) + { + /* An error should already have been reported. */ + sfree (name); + continue; + } + + cf_ci_append_children (root, temp); + sfree (temp->children); + sfree (temp); + + free (name); + } + + free(filenames); + return (root); +} /* oconfig_item_t *cf_read_dir */ + +/* + * cf_read_generic + * + * Path is stat'ed and either cf_read_file or cf_read_dir is called + * accordingly. + * + * There are two versions of this function: If `wordexp' exists shell wildcards + * will be expanded and the function will include all matches found. If + * `wordexp' (or, more precisely, it's header file) is not available the + * simpler function is used which does not do any such expansion. + */ +#if HAVE_WORDEXP_H +static oconfig_item_t *cf_read_generic (const char *path, + const char *pattern, int depth) +{ + oconfig_item_t *root = NULL; + int status; + const char *path_ptr; + wordexp_t we; + size_t i; + + if (depth >= CF_MAX_DEPTH) + { + ERROR ("configfile: Not including `%s' because the maximum " + "nesting depth has been reached.", path); + return (NULL); + } + + status = wordexp (path, &we, WRDE_NOCMD); + if (status != 0) + { + ERROR ("configfile: wordexp (%s) failed.", path); + return (NULL); + } + + root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t)); + if (root == NULL) + { + ERROR ("configfile: malloc failed."); + return (NULL); + } + memset (root, '\0', sizeof (oconfig_item_t)); + + /* wordexp() might return a sorted list already. That's not + * documented though, so let's make sure we get what we want. */ + qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv), + cf_compare_string); + + for (i = 0; i < we.we_wordc; i++) + { + oconfig_item_t *temp; + struct stat statbuf; + + path_ptr = we.we_wordv[i]; + + status = stat (path_ptr, &statbuf); + if (status != 0) + { + char errbuf[1024]; + WARNING ("configfile: stat (%s) failed: %s", + path_ptr, + sstrerror (errno, errbuf, sizeof (errbuf))); + continue; + } + + if (S_ISREG (statbuf.st_mode)) + temp = cf_read_file (path_ptr, pattern, depth); + else if (S_ISDIR (statbuf.st_mode)) + temp = cf_read_dir (path_ptr, pattern, depth); + else + { + WARNING ("configfile: %s is neither a file nor a " + "directory.", path); + continue; + } + + if (temp == NULL) { + oconfig_free (root); + return (NULL); + } + + cf_ci_append_children (root, temp); + sfree (temp->children); + sfree (temp); + } + + wordfree (&we); + + return (root); +} /* oconfig_item_t *cf_read_generic */ +/* #endif HAVE_WORDEXP_H */ + +#else /* if !HAVE_WORDEXP_H */ +static oconfig_item_t *cf_read_generic (const char *path, + const char *pattern, int depth) +{ + struct stat statbuf; + int status; + + if (depth >= CF_MAX_DEPTH) + { + ERROR ("configfile: Not including `%s' because the maximum " + "nesting depth has been reached.", path); + return (NULL); + } + + status = stat (path, &statbuf); + if (status != 0) + { + char errbuf[1024]; + ERROR ("configfile: stat (%s) failed: %s", + path, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (NULL); + } + + if (S_ISREG (statbuf.st_mode)) + return (cf_read_file (path, pattern, depth)); + else if (S_ISDIR (statbuf.st_mode)) + return (cf_read_dir (path, pattern, depth)); + + ERROR ("configfile: %s is neither a file nor a directory.", path); + return (NULL); +} /* oconfig_item_t *cf_read_generic */ +#endif /* !HAVE_WORDEXP_H */ + +/* + * Public functions + */ +int global_option_set (const char *option, const char *value) +{ + int i; + + DEBUG ("option = %s; value = %s;", option, value); + + for (i = 0; i < cf_global_options_num; i++) + if (strcasecmp (cf_global_options[i].key, option) == 0) + break; + + if (i >= cf_global_options_num) + return (-1); + + if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1) + { + DEBUG ("Configfile: Ignoring `PIDFILE' option because " + "command-line option `-P' take precedence."); + return (0); + } + + sfree (cf_global_options[i].value); + + if (value != NULL) + cf_global_options[i].value = strdup (value); + else + cf_global_options[i].value = NULL; + + return (0); +} + +const char *global_option_get (const char *option) +{ + int i; + + for (i = 0; i < cf_global_options_num; i++) + if (strcasecmp (cf_global_options[i].key, option) == 0) + break; + + if (i >= cf_global_options_num) + return (NULL); + + return ((cf_global_options[i].value != NULL) + ? cf_global_options[i].value + : cf_global_options[i].def); +} /* char *global_option_get */ + +long global_option_get_long (const char *option, long default_value) +{ + const char *str; + long value; + + str = global_option_get (option); + if (NULL == str) + return (default_value); + + errno = 0; + value = strtol (str, /* endptr = */ NULL, /* base = */ 0); + if (errno != 0) + return (default_value); + + return (value); +} /* char *global_option_get_long */ + +cdtime_t global_option_get_time (const char *name, cdtime_t def) /* {{{ */ +{ + char const *optstr; + char *endptr = NULL; + double v; + + optstr = global_option_get (name); + if (optstr == NULL) + return (def); + + errno = 0; + v = strtod (optstr, &endptr); + if ((endptr == NULL) || (*endptr != 0) || (errno != 0)) + return (def); + else if (v <= 0.0) + return (def); + + return (DOUBLE_TO_CDTIME_T (v)); +} /* }}} cdtime_t global_option_get_time */ + +cdtime_t cf_get_default_interval (void) +{ + return (global_option_get_time ("Interval", + DOUBLE_TO_CDTIME_T (COLLECTD_DEFAULT_INTERVAL))); +} + +void cf_unregister (const char *type) +{ + cf_callback_t *this, *prev; + + for (prev = NULL, this = first_callback; + this != NULL; + prev = this, this = this->next) + if (strcasecmp (this->type, type) == 0) + { + if (prev == NULL) + first_callback = this->next; + else + prev->next = this->next; + + free (this); + break; + } +} /* void cf_unregister */ + +void cf_unregister_complex (const char *type) +{ + cf_complex_callback_t *this, *prev; + + for (prev = NULL, this = complex_callback_head; + this != NULL; + prev = this, this = this->next) + if (strcasecmp (this->type, type) == 0) + { + if (prev == NULL) + complex_callback_head = this->next; + else + prev->next = this->next; + + sfree (this->type); + sfree (this); + break; + } +} /* void cf_unregister */ + +void cf_register (const char *type, + int (*callback) (const char *, const char *), + const char **keys, int keys_num) +{ + cf_callback_t *cf_cb; + + /* Remove this module from the list, if it already exists */ + cf_unregister (type); + + /* This pointer will be free'd in `cf_unregister' */ + if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL) + return; + + cf_cb->type = type; + cf_cb->callback = callback; + cf_cb->keys = keys; + cf_cb->keys_num = keys_num; + cf_cb->ctx = plugin_get_ctx (); + + cf_cb->next = first_callback; + first_callback = cf_cb; +} /* void cf_register */ + +int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *)) +{ + cf_complex_callback_t *new; + + new = (cf_complex_callback_t *) malloc (sizeof (cf_complex_callback_t)); + if (new == NULL) + return (-1); + + new->type = strdup (type); + if (new->type == NULL) + { + sfree (new); + return (-1); + } + + new->callback = callback; + new->next = NULL; + + new->ctx = plugin_get_ctx (); + + if (complex_callback_head == NULL) + { + complex_callback_head = new; + } + else + { + cf_complex_callback_t *last = complex_callback_head; + while (last->next != NULL) + last = last->next; + last->next = new; + } + + return (0); +} /* int cf_register_complex */ + +int cf_read (char *filename) +{ + oconfig_item_t *conf; + int i; + + conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0); + if (conf == NULL) + { + ERROR ("Unable to read config file %s.", filename); + return (-1); + } + else if (conf->children_num == 0) + { + ERROR ("Configuration file %s is empty.", filename); + oconfig_free (conf); + return (-1); + } + + for (i = 0; i < conf->children_num; i++) + { + if (conf->children[i].children == NULL) + dispatch_value (conf->children + i); + else + dispatch_block (conf->children + i); + } + + oconfig_free (conf); + + /* Read the default types.db if no `TypesDB' option was given. */ + if (cf_default_typesdb) + read_types_list (PKGDATADIR"/types.db"); + + return (0); +} /* int cf_read */ + +/* Assures the config option is a string, duplicates it and returns the copy in + * "ret_string". If necessary "*ret_string" is freed first. Returns zero upon + * success. */ +int cf_util_get_string (const oconfig_item_t *ci, char **ret_string) /* {{{ */ +{ + char *string; + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + ERROR ("cf_util_get_string: The %s option requires " + "exactly one string argument.", ci->key); + return (-1); + } + + string = strdup (ci->values[0].value.string); + if (string == NULL) + return (-1); + + if (*ret_string != NULL) + sfree (*ret_string); + *ret_string = string; + + return (0); +} /* }}} int cf_util_get_string */ + +/* Assures the config option is a string and copies it to the provided buffer. + * Assures null-termination. */ +int cf_util_get_string_buffer (const oconfig_item_t *ci, char *buffer, /* {{{ */ + size_t buffer_size) +{ + if ((ci == NULL) || (buffer == NULL) || (buffer_size < 1)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + ERROR ("cf_util_get_string_buffer: The %s option requires " + "exactly one string argument.", ci->key); + return (-1); + } + + strncpy (buffer, ci->values[0].value.string, buffer_size); + buffer[buffer_size - 1] = 0; + + return (0); +} /* }}} int cf_util_get_string_buffer */ + +/* Assures the config option is a number and returns it as an int. */ +int cf_util_get_int (const oconfig_item_t *ci, int *ret_value) /* {{{ */ +{ + if ((ci == NULL) || (ret_value == NULL)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + { + ERROR ("cf_util_get_int: The %s option requires " + "exactly one numeric argument.", ci->key); + return (-1); + } + + *ret_value = (int) ci->values[0].value.number; + + return (0); +} /* }}} int cf_util_get_int */ + +int cf_util_get_double (const oconfig_item_t *ci, double *ret_value) /* {{{ */ +{ + if ((ci == NULL) || (ret_value == NULL)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + { + ERROR ("cf_util_get_double: The %s option requires " + "exactly one numeric argument.", ci->key); + return (-1); + } + + *ret_value = ci->values[0].value.number; + + return (0); +} /* }}} int cf_util_get_double */ + +int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */ +{ + if ((ci == NULL) || (ret_bool == NULL)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) + { + ERROR ("cf_util_get_boolean: The %s option requires " + "exactly one boolean argument.", ci->key); + return (-1); + } + + *ret_bool = ci->values[0].value.boolean ? 1 : 0; + + return (0); +} /* }}} int cf_util_get_boolean */ + +int cf_util_get_flag (const oconfig_item_t *ci, /* {{{ */ + unsigned int *ret_value, unsigned int flag) +{ + int status; + _Bool b; + + if (ret_value == NULL) + return (EINVAL); + + b = 0; + status = cf_util_get_boolean (ci, &b); + if (status != 0) + return (status); + + if (b) + { + *ret_value |= flag; + } + else + { + *ret_value &= ~flag; + } + + return (0); +} /* }}} int cf_util_get_flag */ + +/* Assures that the config option is a string or a number if the correct range + * of 1-65535. The string is then converted to a port number using + * `service_name_to_port_number' and returned. + * Returns the port number in the range [1-65535] or less than zero upon + * failure. */ +int cf_util_get_port_number (const oconfig_item_t *ci) /* {{{ */ +{ + int tmp; + + if ((ci->values_num != 1) + || ((ci->values[0].type != OCONFIG_TYPE_STRING) + && (ci->values[0].type != OCONFIG_TYPE_NUMBER))) + { + ERROR ("cf_util_get_port_number: The \"%s\" option requires " + "exactly one string argument.", ci->key); + return (-1); + } + + if (ci->values[0].type == OCONFIG_TYPE_STRING) + return (service_name_to_port_number (ci->values[0].value.string)); + + assert (ci->values[0].type == OCONFIG_TYPE_NUMBER); + tmp = (int) (ci->values[0].value.number + 0.5); + if ((tmp < 1) || (tmp > 65535)) + { + ERROR ("cf_util_get_port_number: The \"%s\" option requires " + "a service name or a port number. The number " + "you specified, %i, is not in the valid " + "range of 1-65535.", + ci->key, tmp); + return (-1); + } + + return (tmp); +} /* }}} int cf_util_get_port_number */ + +int cf_util_get_service (const oconfig_item_t *ci, char **ret_string) /* {{{ */ +{ + int port; + char *service; + int status; + + if (ci->values_num != 1) + { + ERROR ("cf_util_get_service: The %s option requires exactly " + "one argument.", ci->key); + return (-1); + } + + if (ci->values[0].type == OCONFIG_TYPE_STRING) + return (cf_util_get_string (ci, ret_string)); + if (ci->values[0].type != OCONFIG_TYPE_NUMBER) + { + ERROR ("cf_util_get_service: The %s option requires " + "exactly one string or numeric argument.", + ci->key); + } + + port = 0; + status = cf_util_get_int (ci, &port); + if (status != 0) + return (status); + else if ((port < 1) || (port > 65535)) + { + ERROR ("cf_util_get_service: The port number given " + "for the %s option is out of " + "range (%i).", ci->key, port); + return (-1); + } + + service = malloc (6); + if (service == NULL) + { + ERROR ("cf_util_get_service: Out of memory."); + return (-1); + } + ssnprintf (service, 6, "%i", port); + + sfree (*ret_string); + *ret_string = service; + + return (0); +} /* }}} int cf_util_get_service */ + +int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */ +{ + if ((ci == NULL) || (ret_value == NULL)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + { + ERROR ("cf_util_get_cdtime: The %s option requires " + "exactly one numeric argument.", ci->key); + return (-1); + } + + if (ci->values[0].value.number < 0.0) + { + ERROR ("cf_util_get_cdtime: The numeric argument of the %s " + "option must not be negative.", ci->key); + return (-1); + } + + *ret_value = DOUBLE_TO_CDTIME_T (ci->values[0].value.number); + + return (0); +} /* }}} int cf_util_get_cdtime */ + diff --combined src/df.c index a6fa526a,ae09e6b7..61964f3c --- a/src/df.c +++ b/src/df.c @@@ -17,7 -17,7 +17,7 @@@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster * Paul Sadauskas **/ @@@ -208,10 -208,11 +208,11 @@@ static int df_read (void uint64_t blk_reserved; uint64_t blk_used; - if (ignorelist_match (il_device, - (mnt_ptr->spec_device != NULL) - ? mnt_ptr->spec_device - : mnt_ptr->device)) + char const *dev = (mnt_ptr->spec_device != NULL) + ? mnt_ptr->spec_device + : mnt_ptr->device; + + if (ignorelist_match (il_device, dev)) continue; if (ignorelist_match (il_mountpoint, mnt_ptr->dir)) continue; @@@ -234,10 -235,10 +235,10 @@@ if (by_device) { /* eg, /dev/hda1 -- strip off the "/dev/" */ - if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0) - sstrncpy (disk_name, mnt_ptr->spec_device + strlen ("/dev/"), sizeof (disk_name)); + if (strncmp (dev, "/dev/", strlen ("/dev/")) == 0) + sstrncpy (disk_name, dev + strlen ("/dev/"), sizeof (disk_name)); else - sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name)); + sstrncpy (disk_name, dev, sizeof (disk_name)); if (strlen(disk_name) < 1) { diff --combined src/snmp.c index 7e40392c,4dd1d10c..260eff16 --- a/src/snmp.c +++ b/src/snmp.c @@@ -2,23 -2,18 +2,23 @@@ * collectd - src/snmp.c * Copyright (C) 2007-2012 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. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * 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 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: * Florian octo Forster @@@ -34,8 -29,6 +34,8 @@@ #include #include +#include + /* * Private data structes */ @@@ -57,7 -50,7 +57,7 @@@ struct data_definition_ { char *name; /* used to reference this from the `Collect' option */ char *type; /* used to find the data_set */ - int is_table; + _Bool is_table; instance_t instance; char *instance_prefix; oid_t *values; @@@ -65,9 -58,6 +65,9 @@@ double scale; double shift; struct data_definition_s *next; + char **ignores; + size_t ignores_len; + int invert_match; }; typedef struct data_definition_s data_definition_t; @@@ -75,22 -65,8 +75,22 @@@ struct host_definition_ { char *name; char *address; - char *community; int version; + + /* snmpv1/2 options */ + char *community; + + /* snmpv3 security options */ + char *username; + oid *auth_protocol; + size_t auth_protocol_len; + char *auth_passphrase; + oid *priv_protocol; + size_t priv_protocol_len; + char *priv_passphrase; + int security_level; + char *context; + void *sess_handle; c_complain_t complaint; cdtime_t interval; @@@ -207,10 -183,6 +207,10 @@@ static void csnmp_host_definition_destr sfree (hd->name); sfree (hd->address); sfree (hd->community); + sfree (hd->username); + sfree (hd->auth_passphrase); + sfree (hd->priv_passphrase); + sfree (hd->context); sfree (hd->data_list); sfree (hd); @@@ -225,15 -197,16 +225,15 @@@ * csnmp_config * +-> call_snmp_init_once * +-> csnmp_config_add_data - * ! +-> csnmp_config_add_data_type - * ! +-> csnmp_config_add_data_table * ! +-> csnmp_config_add_data_instance * ! +-> csnmp_config_add_data_instance_prefix * ! +-> csnmp_config_add_data_values * +-> csnmp_config_add_host - * +-> csnmp_config_add_host_address - * +-> csnmp_config_add_host_community * +-> csnmp_config_add_host_version * +-> csnmp_config_add_host_collect + * +-> csnmp_config_add_host_auth_protocol + * +-> csnmp_config_add_host_priv_protocol + * +-> csnmp_config_add_host_security_level */ static void call_snmp_init_once (void) { @@@ -244,31 -217,60 +244,31 @@@ have_init = 1; } /* void call_snmp_init_once */ -static int csnmp_config_add_data_type (data_definition_t *dd, oconfig_item_t *ci) -{ - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: `Type' needs exactly one string argument."); - return (-1); - } - - sfree (dd->type); - dd->type = strdup (ci->values[0].value.string); - if (dd->type == NULL) - return (-1); - - return (0); -} /* int csnmp_config_add_data_type */ - -static int csnmp_config_add_data_table (data_definition_t *dd, oconfig_item_t *ci) -{ - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) - { - WARNING ("snmp plugin: `Table' needs exactly one boolean argument."); - return (-1); - } - - dd->is_table = ci->values[0].value.boolean ? 1 : 0; - - return (0); -} /* int csnmp_config_add_data_table */ - static int csnmp_config_add_data_instance (data_definition_t *dd, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: `Instance' needs exactly one string argument."); - return (-1); - } + char buffer[DATA_MAX_NAME_LEN]; + int status; + + status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + if (status != 0) + return status; if (dd->is_table) { /* Instance is an OID */ dd->instance.oid.oid_len = MAX_OID_LEN; - if (!read_objid (ci->values[0].value.string, + if (!read_objid (buffer, dd->instance.oid.oid, &dd->instance.oid.oid_len)) { - ERROR ("snmp plugin: read_objid (%s) failed.", - ci->values[0].value.string); + ERROR ("snmp plugin: read_objid (%s) failed.", buffer); return (-1); } } else { /* Instance is a simple string */ - sstrncpy (dd->instance.string, ci->values[0].value.string, + sstrncpy (dd->instance.string, buffer, sizeof (dd->instance.string)); } @@@ -278,7 -280,11 +278,7 @@@ static int csnmp_config_add_data_instance_prefix (data_definition_t *dd, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: `InstancePrefix' needs exactly one string argument."); - return (-1); - } + int status; if (!dd->is_table) { @@@ -287,8 -293,12 +287,8 @@@ return (-1); } - sfree (dd->instance_prefix); - dd->instance_prefix = strdup (ci->values[0].value.string); - if (dd->instance_prefix == NULL) - return (-1); - - return (0); + status = cf_util_get_string(ci, &dd->instance_prefix); + return status; } /* int csnmp_config_add_data_instance_prefix */ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci) @@@ -334,49 -344,33 +334,49 @@@ return (0); } /* int csnmp_config_add_data_instance */ -static int csnmp_config_add_data_shift (data_definition_t *dd, oconfig_item_t *ci) +static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci) { - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + int i; + + if (ci->values_num < 1) + return (0); + + for (i = 0; i < ci->values_num; i++) { - WARNING ("snmp plugin: The `Shift' config option needs exactly one number argument."); - return (-1); + if (ci->values[i].type != OCONFIG_TYPE_STRING) + { + WARNING ("snmp plugin: `Ignore' needs only string argument."); + return (-1); + } } - dd->shift = ci->values[0].value.number; + dd->ignores_len = 0; + dd->ignores = NULL; - return (0); -} /* int csnmp_config_add_data_shift */ + for (i = 0; i < ci->values_num; ++i) + { + if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0) + { + ERROR("snmp plugin: Can't allocate memory"); + strarray_free(dd->ignores, dd->ignores_len); + return (ENOMEM); + } + } + return 0; +} /* int csnmp_config_add_data_blacklist */ -static int csnmp_config_add_data_scale (data_definition_t *dd, oconfig_item_t *ci) +static int csnmp_config_add_data_blacklist_match_inverted(data_definition_t *dd, oconfig_item_t *ci) { - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) { - WARNING ("snmp plugin: The `Scale' config option needs exactly one number argument."); + WARNING ("snmp plugin: `InvertMatch' needs exactly one boolean argument."); return (-1); } - dd->scale = ci->values[0].value.number; + dd->invert_match = ci->values[0].value.boolean ? 1 : 0; return (0); -} /* int csnmp_config_add_data_scale */ +} /* int csnmp_config_add_data_blacklist_match_inverted */ static int csnmp_config_add_data (oconfig_item_t *ci) { @@@ -384,18 -378,24 +384,18 @@@ int status = 0; int i; - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: The `Data' config option needs exactly one string argument."); - return (-1); - } - dd = (data_definition_t *) malloc (sizeof (data_definition_t)); if (dd == NULL) return (-1); memset (dd, '\0', sizeof (data_definition_t)); - dd->name = strdup (ci->values[0].value.string); - if (dd->name == NULL) + status = cf_util_get_string(ci, &dd->name); + if (status != 0) { free (dd); return (-1); } + dd->scale = 1.0; dd->shift = 0.0; @@@ -404,9 -404,9 +404,9 @@@ oconfig_item_t *option = ci->children + i; if (strcasecmp ("Type", option->key) == 0) - status = csnmp_config_add_data_type (dd, option); + status = cf_util_get_string(option, &dd->type); else if (strcasecmp ("Table", option->key) == 0) - status = csnmp_config_add_data_table (dd, option); + status = cf_util_get_boolean(option, &dd->is_table); else if (strcasecmp ("Instance", option->key) == 0) status = csnmp_config_add_data_instance (dd, option); else if (strcasecmp ("InstancePrefix", option->key) == 0) @@@ -414,13 -414,9 +414,13 @@@ else if (strcasecmp ("Values", option->key) == 0) status = csnmp_config_add_data_values (dd, option); else if (strcasecmp ("Shift", option->key) == 0) - status = csnmp_config_add_data_shift (dd, option); + status = cf_util_get_double(option, &dd->shift); else if (strcasecmp ("Scale", option->key) == 0) - status = csnmp_config_add_data_scale (dd, option); + status = cf_util_get_double(option, &dd->scale); + else if (strcasecmp ("Ignore", option->key) == 0) + status = csnmp_config_add_data_blacklist(dd, option); + else if (strcasecmp ("InvertMatch", option->key) == 0) + status = csnmp_config_add_data_blacklist_match_inverted(dd, option); else { WARNING ("snmp plugin: Option `%s' not allowed here.", option->key); @@@ -454,7 -450,6 +454,7 @@@ sfree (dd->name); sfree (dd->instance_prefix); sfree (dd->values); + sfree (dd->ignores); sfree (dd); return (-1); } @@@ -476,6 -471,50 +476,6 @@@ return (0); } /* int csnmp_config_add_data */ -static int csnmp_config_add_host_address (host_definition_t *hd, oconfig_item_t *ci) -{ - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: The `Address' config option needs exactly one string argument."); - return (-1); - } - - if (hd->address == NULL) - free (hd->address); - - hd->address = strdup (ci->values[0].value.string); - if (hd->address == NULL) - return (-1); - - DEBUG ("snmp plugin: host = %s; host->address = %s;", - hd->name, hd->address); - - return (0); -} /* int csnmp_config_add_host_address */ - -static int csnmp_config_add_host_community (host_definition_t *hd, oconfig_item_t *ci) -{ - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: The `Community' config option needs exactly one string argument."); - return (-1); - } - - if (hd->community == NULL) - free (hd->community); - - hd->community = strdup (ci->values[0].value.string); - if (hd->community == NULL) - return (-1); - - DEBUG ("snmp plugin: host = %s; host->community = %s;", - hd->name, hd->community); - - return (0); -} /* int csnmp_config_add_host_community */ - static int csnmp_config_add_host_version (host_definition_t *hd, oconfig_item_t *ci) { int version; @@@ -488,9 -527,9 +488,9 @@@ } version = (int) ci->values[0].value.number; - if ((version != 1) && (version != 2)) + if ((version < 1) || (version > 3)) { - WARNING ("snmp plugin: `Version' must either be `1' or `2'."); + WARNING ("snmp plugin: `Version' must either be `1', `2', or `3'."); return (-1); } @@@ -550,92 -589,6 +550,92 @@@ static int csnmp_config_add_host_collec return (0); } /* int csnmp_config_add_host_collect */ +static int csnmp_config_add_host_auth_protocol (host_definition_t *hd, oconfig_item_t *ci) +{ + char buffer[4]; + int status; + + status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + if (status != 0) + return status; + + if (strcasecmp("MD5", buffer) == 0) { + hd->auth_protocol = usmHMACMD5AuthProtocol; + hd->auth_protocol_len = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid); + } + else if (strcasecmp("SHA", buffer) == 0) { + hd->auth_protocol = usmHMACSHA1AuthProtocol; + hd->auth_protocol_len = sizeof(usmHMACSHA1AuthProtocol)/sizeof(oid); + } + else + { + WARNING ("snmp plugin: The `AuthProtocol' config option must be `MD5' or `SHA'."); + return (-1); + } + + DEBUG ("snmp plugin: host = %s; host->auth_protocol = %s;", + hd->name, hd->auth_protocol == usmHMACMD5AuthProtocol ? "MD5" : "SHA"); + + return (0); +} /* int csnmp_config_add_host_auth_protocol */ + +static int csnmp_config_add_host_priv_protocol (host_definition_t *hd, oconfig_item_t *ci) +{ + char buffer[4]; + int status; + + status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + if (status != 0) + return status; + + if (strcasecmp("AES", buffer) == 0) + { + hd->priv_protocol = usmAESPrivProtocol; + hd->priv_protocol_len = sizeof(usmAESPrivProtocol)/sizeof(oid); + } + else if (strcasecmp("DES", buffer) == 0) { + hd->priv_protocol = usmDESPrivProtocol; + hd->priv_protocol_len = sizeof(usmDESPrivProtocol)/sizeof(oid); + } + else + { + WARNING ("snmp plugin: The `PrivProtocol' config option must be `AES' or `DES'."); + return (-1); + } + + DEBUG ("snmp plugin: host = %s; host->priv_protocol = %s;", + hd->name, hd->priv_protocol == usmAESPrivProtocol ? "AES" : "DES"); + + return (0); +} /* int csnmp_config_add_host_priv_protocol */ + +static int csnmp_config_add_host_security_level (host_definition_t *hd, oconfig_item_t *ci) +{ + char buffer[16]; + int status; + + status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + if (status != 0) + return status; + + if (strcasecmp("noAuthNoPriv", buffer) == 0) + hd->security_level = SNMP_SEC_LEVEL_NOAUTH; + else if (strcasecmp("authNoPriv", buffer) == 0) + hd->security_level = SNMP_SEC_LEVEL_AUTHNOPRIV; + else if (strcasecmp("authPriv", buffer) == 0) + hd->security_level = SNMP_SEC_LEVEL_AUTHPRIV; + else + { + WARNING ("snmp plugin: The `SecurityLevel' config option must be `noAuthNoPriv', `authNoPriv', or `authPriv'."); + return (-1); + } + + DEBUG ("snmp plugin: host = %s; host->security_level = %d;", + hd->name, hd->security_level); + + return (0); +} /* int csnmp_config_add_host_security_level */ + static int csnmp_config_add_host (oconfig_item_t *ci) { host_definition_t *hd; @@@ -647,6 -600,12 +647,6 @@@ user_data_t cb_data; struct timespec cb_interval; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("snmp plugin: `Host' needs exactly one string argument."); - return (-1); - } - hd = (host_definition_t *) malloc (sizeof (host_definition_t)); if (hd == NULL) return (-1); @@@ -654,9 -613,12 +654,9 @@@ hd->version = 2; C_COMPLAIN_INIT (&hd->complaint); - hd->name = strdup (ci->values[0].value.string); - if (hd->name == NULL) - { - free (hd); - return (-1); - } + status = cf_util_get_string(ci, &hd->name); + if (status != 0) + return status; hd->sess_handle = NULL; hd->interval = 0; @@@ -667,29 -629,15 +667,29 @@@ status = 0; if (strcasecmp ("Address", option->key) == 0) - status = csnmp_config_add_host_address (hd, option); + status = cf_util_get_string(option, &hd->address); else if (strcasecmp ("Community", option->key) == 0) - status = csnmp_config_add_host_community (hd, option); + status = cf_util_get_string(option, &hd->community); else if (strcasecmp ("Version", option->key) == 0) status = csnmp_config_add_host_version (hd, option); else if (strcasecmp ("Collect", option->key) == 0) csnmp_config_add_host_collect (hd, option); else if (strcasecmp ("Interval", option->key) == 0) cf_util_get_cdtime (option, &hd->interval); + else if (strcasecmp ("Username", option->key) == 0) + status = cf_util_get_string(option, &hd->username); + else if (strcasecmp ("AuthProtocol", option->key) == 0) + status = csnmp_config_add_host_auth_protocol (hd, option); + else if (strcasecmp ("PrivacyProtocol", option->key) == 0) + status = csnmp_config_add_host_priv_protocol (hd, option); + else if (strcasecmp ("AuthPassphrase", option->key) == 0) + status = cf_util_get_string(option, &hd->auth_passphrase); + else if (strcasecmp ("PrivacyPassphrase", option->key) == 0) + status = cf_util_get_string(option, &hd->priv_passphrase); + else if (strcasecmp ("SecurityLevel", option->key) == 0) + status = csnmp_config_add_host_security_level (hd, option); + else if (strcasecmp ("Context", option->key) == 0) + status = cf_util_get_string(option, &hd->context); else { WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key); @@@ -708,57 -656,12 +708,57 @@@ status = -1; break; } - if (hd->community == NULL) + if (hd->community == NULL && hd->version < 3) { WARNING ("snmp plugin: `Community' not given for host `%s'", hd->name); status = -1; break; } + if (hd->version == 3) + { + if (hd->username == NULL) + { + WARNING ("snmp plugin: `Username' not given for host `%s'", hd->name); + status = -1; + break; + } + if (hd->security_level == 0) + { + WARNING ("snmp plugin: `SecurityLevel' not given for host `%s'", hd->name); + status = -1; + break; + } + if (hd->security_level == SNMP_SEC_LEVEL_AUTHNOPRIV || hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV) + { + if (hd->auth_protocol == NULL) + { + WARNING ("snmp plugin: `AuthProtocol' not given for host `%s'", hd->name); + status = -1; + break; + } + if (hd->auth_passphrase == NULL) + { + WARNING ("snmp plugin: `AuthPassphrase' not given for host `%s'", hd->name); + status = -1; + break; + } + } + if (hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV) + { + if (hd->priv_protocol == NULL) + { + WARNING ("snmp plugin: `PrivacyProtocol' not given for host `%s'", hd->name); + status = -1; + break; + } + if (hd->priv_passphrase == NULL) + { + WARNING ("snmp plugin: `PrivacyPassphrase' not given for host `%s'", hd->name); + status = -1; + break; + } + } + } break; } /* while (status == 0) */ @@@ -820,75 -723,15 +820,75 @@@ static int csnmp_config (oconfig_item_ static void csnmp_host_open_session (host_definition_t *host) { struct snmp_session sess; + int error; if (host->sess_handle != NULL) csnmp_host_close_session (host); snmp_sess_init (&sess); sess.peername = host->address; - sess.community = (u_char *) host->community; - sess.community_len = strlen (host->community); - sess.version = (host->version == 1) ? SNMP_VERSION_1 : SNMP_VERSION_2c; + switch (host->version) + { + case 1: + sess.version = SNMP_VERSION_1; + break; + case 3: + sess.version = SNMP_VERSION_3; + break; + default: + sess.version = SNMP_VERSION_2c; + break; + } + + if (host->version == 3) + { + sess.securityName = host->username; + sess.securityNameLen = strlen (host->username); + sess.securityLevel = host->security_level; + + if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + sess.securityAuthProto = host->auth_protocol; + sess.securityAuthProtoLen = host->auth_protocol_len; + sess.securityAuthKeyLen = USM_AUTH_KU_LEN; + error = generate_Ku (sess.securityAuthProto, + sess.securityAuthProtoLen, + (u_char *) host->auth_passphrase, + strlen(host->auth_passphrase), + sess.securityAuthKey, + &sess.securityAuthKeyLen); + if (error != SNMPERR_SUCCESS) { + ERROR ("snmp plugin: host %s: Error generating Ku from auth_passphrase. (Error %d)", host->name, error); + } + } + + if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + sess.securityPrivProto = host->priv_protocol; + sess.securityPrivProtoLen = host->priv_protocol_len; + sess.securityPrivKeyLen = USM_PRIV_KU_LEN; + error = generate_Ku (sess.securityAuthProto, + sess.securityAuthProtoLen, + (u_char *) host->priv_passphrase, + strlen(host->priv_passphrase), + sess.securityPrivKey, + &sess.securityPrivKeyLen); + if (error != SNMPERR_SUCCESS) { + ERROR ("snmp plugin: host %s: Error generating Ku from priv_passphrase. (Error %d)", host->name, error); + } + } + + if (host->context != NULL) + { + sess.contextName = host->context; + sess.contextNameLen = strlen (host->context); + } + } + else /* SNMPv1/2 "authenticates" with community string */ + { + sess.community = (u_char *) host->community; + sess.community_len = strlen (host->community); + } /* snmp_sess_open will copy the `struct snmp_session *'. */ host->sess_handle = snmp_sess_open (&sess); @@@ -992,8 -835,7 +992,8 @@@ static value_t csnmp_value_list_to_valu status = parse_value (string, &ret, type); if (status != 0) { - ERROR ("snmp plugin: csnmp_value_list_to_value: Parsing string as %s failed: %s", + ERROR ("snmp plugin: host %s: csnmp_value_list_to_value: Parsing string as %s failed: %s", + (host_name != NULL) ? host_name : "UNKNOWN", DS_TYPE_TO_STRING (type), string); } } @@@ -1128,8 -970,6 +1128,8 @@@ static int csnmp_instance_list_add (csn struct variable_list *vb; oid_t vb_name; int status; + uint32_t i; + uint32_t is_matched; /* Set vb on the last variable */ for (vb = res->variables; @@@ -1163,29 -1003,7 +1163,29 @@@ char *ptr; csnmp_strvbcopy (il->instance, vb, sizeof (il->instance)); - + is_matched = 0; + for (i = 0; i < dd->ignores_len; i++) + { + status = fnmatch(dd->ignores[i], il->instance, 0); + if (status == 0) + { + if (dd->invert_match == 0) + { + sfree(il); + return 0; + } + else + { + is_matched = 1; + break; + } + } + } + if (dd->invert_match != 0 && is_matched == 0) + { + sfree(il); + return 0; + } for (ptr = il->instance; *ptr != '\0'; ptr++) { if ((*ptr > 0) && (*ptr < 32)) @@@ -1423,6 -1241,7 +1423,7 @@@ static int csnmp_read_table (host_defin data->type, ds->ds_num, data->values_len); return (-1); } + assert (data->values_len > 0); /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ memcpy (oid_list, data->values, data->values_len * sizeof (oid_t)); @@@ -1546,8 -1365,7 +1547,8 @@@ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail, res, host, data) != 0) { - ERROR ("snmp plugin: csnmp_instance_list_add failed."); + ERROR ("snmp plugin: host %s: csnmp_instance_list_add failed.", + host->name); status = -1; break; } @@@ -1843,7 -1661,6 +1844,7 @@@ static int csnmp_shutdown (void sfree (data_this->name); sfree (data_this->type); sfree (data_this->values); + sfree (data_this->ignores); sfree (data_this); data_this = data_next; diff --combined src/table.c index c6b5badf,a3bacc7a..beded1ae --- a/src/table.c +++ b/src/table.c @@@ -1,24 -1,19 +1,24 @@@ /** * collectd - src/table.c - * Copyright (C) 2009 Sebastian Harl + * Copyright (C) 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 - * Free Software Foundation; only version 2 of the License is applicable. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * 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 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: * Sebastian Harl @@@ -283,8 -278,9 +283,9 @@@ static int tbl_config_table (oconfig_it if (NULL == tbl->sep) { log_err ("Table \"%s\" does not specify any separator.", tbl->file); status = 1; + } else { + strunescape (tbl->sep, strlen (tbl->sep) + 1); } - strunescape (tbl->sep, strlen (tbl->sep) + 1); if (NULL == tbl->instance) { tbl->instance = sstrdup (tbl->file); diff --combined src/threshold.c index 882f9553,4a840bb9..a8900db7 --- a/src/threshold.c +++ b/src/threshold.c @@@ -28,17 -28,75 +28,17 @@@ #include "plugin.h" #include "utils_avltree.h" #include "utils_cache.h" +#include "utils_threshold.h" #include #include /* - * Private data structures - * {{{ */ -#define UT_FLAG_INVERT 0x01 -#define UT_FLAG_PERSIST 0x02 -#define UT_FLAG_PERCENTAGE 0x04 -#define UT_FLAG_INTERESTING 0x08 -#define UT_FLAG_PERSIST_OK 0x10 -typedef struct threshold_s -{ - char host[DATA_MAX_NAME_LEN]; - char plugin[DATA_MAX_NAME_LEN]; - char plugin_instance[DATA_MAX_NAME_LEN]; - char type[DATA_MAX_NAME_LEN]; - char type_instance[DATA_MAX_NAME_LEN]; - char data_source[DATA_MAX_NAME_LEN]; - gauge_t warning_min; - gauge_t warning_max; - gauge_t failure_min; - gauge_t failure_max; - gauge_t hysteresis; - unsigned int flags; - int hits; - struct threshold_s *next; -} threshold_t; -/* }}} */ - -/* - * Private (static) variables - * {{{ */ -static c_avl_tree_t *threshold_tree = NULL; -static pthread_mutex_t threshold_lock = PTHREAD_MUTEX_INITIALIZER; -/* }}} */ - -/* * Threshold management * ==================== * The following functions add, delete, search, etc. configured thresholds to * the underlying AVL trees. */ -/* - * threshold_t *threshold_get - * - * Retrieve one specific threshold configuration. For looking up a threshold - * matching a value_list_t, see "threshold_search" below. Returns NULL if the - * specified threshold doesn't exist. - */ -static threshold_t *threshold_get (const char *hostname, - const char *plugin, const char *plugin_instance, - const char *type, const char *type_instance) -{ /* {{{ */ - char name[6 * DATA_MAX_NAME_LEN]; - threshold_t *th = NULL; - - format_name (name, sizeof (name), - (hostname == NULL) ? "" : hostname, - (plugin == NULL) ? "" : plugin, plugin_instance, - (type == NULL) ? "" : type, type_instance); - name[sizeof (name) - 1] = '\0'; - - if (c_avl_get (threshold_tree, name, (void *) &th) == 0) - return (th); - else - return (NULL); -} /* }}} threshold_t *threshold_get */ /* * int ut_threshold_add @@@ -113,6 -171,58 +113,6 @@@ static int ut_threshold_add (const thre return (status); } /* }}} int ut_threshold_add */ -/* - * threshold_t *threshold_search - * - * Searches for a threshold configuration using all the possible variations of - * "Host", "Plugin" and "Type" blocks. Returns NULL if no threshold could be - * found. - * XXX: This is likely the least efficient function in collectd. - */ -static threshold_t *threshold_search (const value_list_t *vl) -{ /* {{{ */ - threshold_t *th; - - if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, "", NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, "", NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", "", NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", "", NULL, - vl->type, NULL)) != NULL) - return (th); - - return (NULL); -} /* }}} threshold_t *threshold_search */ - /* * Configuration * ============= @@@ -516,11 -626,7 +516,9 @@@ static int ut_report_state (const data_ ": Value is no longer missing."); else status = ssnprintf (buf, bufsize, - ": All data sources are within range again."); + ": All data sources are within range again. " + "Current value of \"%s\" is %f.", + ds->ds[ds_index].name, values[ds_index]); - buf += status; - bufsize -= status; } else { @@@ -588,8 -694,6 +586,6 @@@ (state == STATE_ERROR) ? "failure" : "warning", (values[ds_index] < min) ? min : max); } - buf += status; - bufsize -= status; } plugin_dispatch_notification (&n); @@@ -636,40 -740,23 +632,40 @@@ static int ut_check_one_data_source (co /* XXX: This is an experimental code, not optimized, not fast, not reliable, * and probably, do not work as you expect. Enjoy! :D */ - if ( (th->hysteresis > 0) && ((prev_state = uc_get_state(ds,vl)) != STATE_OKAY) ) - { - switch(prev_state) + if (th->hysteresis > 0) + { + prev_state = uc_get_state(ds,vl); + /* The purpose of hysteresis is elliminating flapping state when the value + * oscilates around the thresholds. In other words, what is important is + * the previous state; if the new value would trigger a transition, make + * sure that we artificially widen the range which is considered to apply + * for the previous state, and only trigger the notification if the value + * is outside of this expanded range. + * + * There is no hysteresis for the OKAY state. + * */ + gauge_t hysteresis_for_warning = 0, hysteresis_for_failure = 0; + switch (prev_state) { case STATE_ERROR: - if ( (!isnan (th->failure_min) && ((th->failure_min + th->hysteresis) < values[ds_index])) || - (!isnan (th->failure_max) && ((th->failure_max - th->hysteresis) > values[ds_index])) ) - return (STATE_OKAY); - else - is_failure++; + hysteresis_for_failure = th->hysteresis; + break; case STATE_WARNING: - if ( (!isnan (th->warning_min) && ((th->warning_min + th->hysteresis) < values[ds_index])) || - (!isnan (th->warning_max) && ((th->warning_max - th->hysteresis) > values[ds_index])) ) - return (STATE_OKAY); - else - is_warning++; - } + hysteresis_for_warning = th->hysteresis; + break; + case STATE_OKAY: + /* do nothing -- the hysteresis only applies to the non-normal states */ + break; + } + + if ((!isnan (th->failure_min) && (th->failure_min + hysteresis_for_failure > values[ds_index])) + || (!isnan (th->failure_max) && (th->failure_max - hysteresis_for_failure < values[ds_index]))) + is_failure++; + + if ((!isnan (th->warning_min) && (th->warning_min + hysteresis_for_warning > values[ds_index])) + || (!isnan (th->warning_max) && (th->warning_max - hysteresis_for_warning < values[ds_index]))) + is_warning++; + } else { /* no hysteresis */ if ((!isnan (th->failure_min) && (th->failure_min > values[ds_index])) @@@ -679,7 -766,7 +675,7 @@@ if ((!isnan (th->warning_min) && (th->warning_min > values[ds_index])) || (!isnan (th->warning_max) && (th->warning_max < values[ds_index]))) is_warning++; - } + } if (is_failure != 0) return (STATE_ERROR); @@@ -768,7 -855,7 +764,7 @@@ static int ut_check_one_threshold (cons * * Gets a list of matching thresholds and searches for the worst status by one * of the thresholds. Then reports that status using the ut_report_state - * function above. + * function above. * Returns zero on success and if no threshold has been configured. Returns * less than zero on failure. */ @@@ -899,7 -986,7 +895,7 @@@ int ut_config (oconfig_item_t *ci th.hits = 0; th.hysteresis = 0; th.flags = UT_FLAG_INTERESTING; /* interesting by default */ - + for (i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; diff --combined src/utils_db_query.c index f29eabcd,e8d7b3aa..9c84937f --- a/src/utils_db_query.c +++ b/src/utils_db_query.c @@@ -2,26 -2,21 +2,26 @@@ * collectd - src/utils_db_query.c * Copyright (C) 2008,2009 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. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * 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 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: - * Florian octo Forster + * Florian octo Forster **/ #include "collectd.h" @@@ -43,8 -38,6 +43,8 @@@ struct udb_result_ size_t instances_num; char **values; size_t values_num; + char **metadata; + size_t metadata_num; udb_result_t *next; }; /* }}} */ @@@ -66,10 -59,8 +66,10 @@@ struct udb_result_preparation_area_s / const data_set_t *ds; size_t *instances_pos; size_t *values_pos; + size_t *metadata_pos; char **instances_buffer; char **values_buffer; + char **metadata_buffer; struct udb_result_preparation_area_s *next; }; /* }}} */ @@@ -197,13 -188,13 +197,14 @@@ static int udb_result_submit (udb_resul { value_list_t vl = VALUE_LIST_INIT; size_t i; + int status; assert (r != NULL); assert (r_area->ds != NULL); assert (((size_t) r_area->ds->ds_num) == r->values_num); + assert (r->values_num > 0); - vl.values = (value_t *) calloc (r_area->ds->ds_num, sizeof (value_t)); + vl.values = (value_t *) calloc (r->values_num, sizeof (value_t)); if (vl.values == NULL) { ERROR ("db query utils: malloc failed."); @@@ -263,38 -254,8 +264,38 @@@ vl.type_instance[sizeof (vl.type_instance) - 1] = 0; /* }}} */ + /* Annotate meta data. {{{ */ + if (r->metadata_num > 0) + { + vl.meta = meta_data_create (); + if (vl.meta == NULL) + { + ERROR ("db query utils:: meta_data_create failed."); + return (-ENOMEM); + } + + for (i = 0; i < r->metadata_num; i++) + { + status = meta_data_add_string (vl.meta, r->metadata[i], + r_area->metadata_buffer[i]); + if (status != 0) + { + ERROR ("db query utils:: meta_data_add_string failed."); + meta_data_destroy (vl.meta); + vl.meta = NULL; + return (status); + } + } + } + /* }}} */ + plugin_dispatch_values (&vl); + if (r->metadata_num > 0) + { + meta_data_destroy (vl.meta); + vl.meta = NULL; + } sfree (vl.values); return (0); } /* }}} void udb_result_submit */ @@@ -308,10 -269,8 +309,10 @@@ static void udb_result_finish_result (u prep_area->ds = NULL; sfree (prep_area->instances_pos); sfree (prep_area->values_pos); + sfree (prep_area->metadata_pos); sfree (prep_area->instances_buffer); sfree (prep_area->values_buffer); + sfree (prep_area->metadata_buffer); } /* }}} void udb_result_finish_result */ static int udb_result_handle_result (udb_result_t *r, /* {{{ */ @@@ -329,9 -288,6 +330,9 @@@ for (i = 0; i < r->values_num; i++) r_area->values_buffer[i] = column_values[r_area->values_pos[i]]; + for (i = 0; i < r->metadata_num; i++) + r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]]; + return udb_result_submit (r, r_area, q, q_area); } /* }}} int udb_result_handle_result */ @@@ -348,17 -304,14 +349,17 @@@ static int udb_result_prepare_result (u prep_area->ds = NULL; \ sfree (prep_area->instances_pos); \ sfree (prep_area->values_pos); \ + sfree (prep_area->metadata_pos); \ sfree (prep_area->instances_buffer); \ sfree (prep_area->values_buffer); \ + sfree (prep_area->metadata_buffer); \ return (status) /* Make sure previous preparations are cleaned up. */ udb_result_finish_result (r, prep_area); prep_area->instances_pos = NULL; prep_area->values_pos = NULL; + prep_area->metadata_pos = NULL; /* Read `ds' and check number of values {{{ */ prep_area->ds = plugin_get_ds (r->type); @@@ -381,8 -334,8 +382,8 @@@ } /* }}} */ - /* Allocate r->instances_pos, r->values_pos, r->instances_buffer, and - * r->values_buffer {{{ */ + /* Allocate r->instances_pos, r->values_pos, r->metadata_post, + * r->instances_buffer, r->values_buffer, and r->metadata_buffer {{{ */ if (r->instances_num > 0) { prep_area->instances_pos @@@ -417,23 -370,6 +418,23 @@@ ERROR ("db query utils: udb_result_prepare_result: malloc failed."); BAIL_OUT (-ENOMEM); } + + prep_area->metadata_pos + = (size_t *) calloc (r->metadata_num, sizeof (size_t)); + if (prep_area->metadata_pos == NULL) + { + ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + BAIL_OUT (-ENOMEM); + } + + prep_area->metadata_buffer + = (char **) calloc (r->metadata_num, sizeof (char *)); + if (prep_area->metadata_buffer == NULL) + { + ERROR ("db query utils: udb_result_prepare_result: malloc failed."); + BAIL_OUT (-ENOMEM); + } + /* }}} */ /* Determine the position of the instance columns {{{ */ @@@ -482,29 -418,6 +483,29 @@@ } } /* }}} for (i = 0; i < r->values_num; i++) */ + /* Determine the position of the metadata columns {{{ */ + for (i = 0; i < r->metadata_num; i++) + { + size_t j; + + for (j = 0; j < column_num; j++) + { + if (strcasecmp (r->metadata[i], column_names[j]) == 0) + { + prep_area->metadata_pos[i] = j; + break; + } + } + + if (j >= column_num) + { + ERROR ("db query utils: udb_result_prepare_result: " + "Metadata column `%s' could not be found.", + r->values[i]); + BAIL_OUT (-ENOENT); + } + } /* }}} for (i = 0; i < r->metadata_num; i++) */ + #undef BAIL_OUT return (0); } /* }}} int udb_result_prepare_result */ @@@ -526,10 -439,6 +527,10 @@@ static void udb_result_free (udb_result sfree (r->values[i]); sfree (r->values); + for (i = 0; i < r->metadata_num; i++) + sfree (r->metadata[i]); + sfree (r->metadata); + udb_result_free (r->next); sfree (r); @@@ -560,7 -469,6 +561,7 @@@ static int udb_result_create (const cha r->instance_prefix = NULL; r->instances = NULL; r->values = NULL; + r->metadata = NULL; r->next = NULL; /* Fill the `udb_result_t' structure.. */ @@@ -577,8 -485,6 +578,8 @@@ status = udb_config_add_string (&r->instances, &r->instances_num, child); else if (strcasecmp ("ValuesFrom", child->key) == 0) status = udb_config_add_string (&r->values, &r->values_num, child); + else if (strcasecmp ("MetadataFrom", child->key) == 0) + status = udb_config_add_string (&r->metadata, &r->metadata_num, child); else { WARNING ("db query utils: Query `%s': Option `%s' not allowed here.", diff --combined src/virt.c index b6fedf55,00000000..dff8f71d mode 100644,000000..100644 --- a/src/virt.c +++ b/src/virt.c @@@ -1,1010 -1,0 +1,1016 @@@ +/** + * collectd - src/virt.c + * Copyright (C) 2006-2008 Red Hat Inc. + * + * 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: + * Richard W.M. Jones + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "configfile.h" +#include "utils_ignorelist.h" +#include "utils_complain.h" + +#include +#include +#include +#include +#include + +/* Plugin name */ +#define PLUGIN_NAME "virt" + +static const char *config_keys[] = { + "Connection", + + "RefreshInterval", + + "Domain", + "BlockDevice", + "InterfaceDevice", + "IgnoreSelected", + + "HostnameFormat", + "InterfaceFormat", + + "PluginInstanceFormat", + + NULL +}; +#define NR_CONFIG_KEYS ((sizeof config_keys / sizeof config_keys[0]) - 1) + +/* Connection. */ +static virConnectPtr conn = 0; +static char *conn_string = NULL; +static c_complain_t conn_complain = C_COMPLAIN_INIT_STATIC; + +/* Seconds between list refreshes, 0 disables completely. */ +static int interval = 60; + +/* List of domains, if specified. */ +static ignorelist_t *il_domains = NULL; +/* List of block devices, if specified. */ +static ignorelist_t *il_block_devices = NULL; +/* List of network interface devices, if specified. */ +static ignorelist_t *il_interface_devices = NULL; + +static int ignore_device_match (ignorelist_t *, + const char *domname, const char *devpath); + +/* Actual list of domains found on last refresh. */ +static virDomainPtr *domains = NULL; +static int nr_domains = 0; + +static void free_domains (void); +static int add_domain (virDomainPtr dom); + +/* Actual list of block devices found on last refresh. */ +struct block_device { + virDomainPtr dom; /* domain */ + char *path; /* name of block device */ +}; + +static struct block_device *block_devices = NULL; +static int nr_block_devices = 0; + +static void free_block_devices (void); +static int add_block_device (virDomainPtr dom, const char *path); + +/* Actual list of network interfaces found on last refresh. */ +struct interface_device { + virDomainPtr dom; /* domain */ + char *path; /* name of interface device */ + char *address; /* mac address of interface device */ + char *number; /* interface device number */ +}; + +static struct interface_device *interface_devices = NULL; +static int nr_interface_devices = 0; + +static void free_interface_devices (void); +static int add_interface_device (virDomainPtr dom, const char *path, const char *address, unsigned int number); + +/* HostnameFormat. */ +#define HF_MAX_FIELDS 3 + +enum hf_field { + hf_none = 0, + hf_hostname, + hf_name, + hf_uuid +}; + +static enum hf_field hostname_format[HF_MAX_FIELDS] = + { hf_name }; + +/* PluginInstanceFormat */ +#define PLGINST_MAX_FIELDS 2 + +enum plginst_field { + plginst_none = 0, + plginst_name, + plginst_uuid +}; + +static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] = + { plginst_name }; + +/* InterfaceFormat. */ +enum if_field { + if_address, + if_name, + if_number +}; + +static enum if_field interface_format = if_name; + +/* Time that we last refreshed. */ +static time_t last_refresh = (time_t) 0; + +static int refresh_lists (void); + +/* ERROR(...) macro for virterrors. */ +#define VIRT_ERROR(conn,s) do { \ + virErrorPtr err; \ + err = (conn) ? virConnGetLastError ((conn)) : virGetLastError (); \ + if (err) ERROR ("%s: %s", (s), err->message); \ + } while(0) + +static void +init_value_list (value_list_t *vl, virDomainPtr dom) +{ + int i, n; + const char *name; + char uuid[VIR_UUID_STRING_BUFLEN]; + + sstrncpy (vl->plugin, PLUGIN_NAME, sizeof (vl->plugin)); + + vl->host[0] = '\0'; + + /* Construct the hostname field according to HostnameFormat. */ + for (i = 0; i < HF_MAX_FIELDS; ++i) { + if (hostname_format[i] == hf_none) + continue; + + n = DATA_MAX_NAME_LEN - strlen (vl->host) - 2; + + if (i > 0 && n >= 1) { + strncat (vl->host, ":", 1); + n--; + } + + switch (hostname_format[i]) { + case hf_none: break; + case hf_hostname: + strncat (vl->host, hostname_g, n); + break; + case hf_name: + name = virDomainGetName (dom); + if (name) + strncat (vl->host, name, n); + break; + case hf_uuid: + if (virDomainGetUUIDString (dom, uuid) == 0) + strncat (vl->host, uuid, n); + break; + } + } + + vl->host[sizeof (vl->host) - 1] = '\0'; + + /* Construct the plugin instance field according to PluginInstanceFormat. */ + for (i = 0; i < PLGINST_MAX_FIELDS; ++i) { + if (plugin_instance_format[i] == plginst_none) + continue; + + n = sizeof(vl->plugin_instance) - strlen (vl->plugin_instance) - 2; + + if (i > 0 && n >= 1) { + strncat (vl->plugin_instance, ":", 1); + n--; + } + + switch (plugin_instance_format[i]) { + case plginst_none: break; + case plginst_name: + name = virDomainGetName (dom); + if (name) + strncat (vl->plugin_instance, name, n); + break; + case plginst_uuid: + if (virDomainGetUUIDString (dom, uuid) == 0) + strncat (vl->plugin_instance, uuid, n); + break; + } + } + + vl->plugin_instance[sizeof (vl->plugin_instance) - 1] = '\0'; + +} /* void init_value_list */ + +static void +memory_submit (gauge_t memory, virDomainPtr dom) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].gauge = memory; + + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, "memory", sizeof (vl.type)); + sstrncpy (vl.type_instance, "total", sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} + +static void +memory_stats_submit (gauge_t memory, virDomainPtr dom, int tag_index) +{ + static const char *tags[] = { "swap_in", "swap_out", "major_fault", "minor_fault", + "unused", "available", "actual_balloon", "rss"}; + + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].gauge = memory; + + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, "memory", sizeof (vl.type)); + sstrncpy (vl.type_instance, tags[tag_index], sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} + +static void +cpu_submit (unsigned long long cpu_time, + virDomainPtr dom, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].derive = cpu_time; + + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, type, sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} + +static void +vcpu_submit (derive_t cpu_time, + virDomainPtr dom, int vcpu_nr, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].derive = cpu_time; + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, type, sizeof (vl.type)); + ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr); + + plugin_dispatch_values (&vl); +} + +static void +submit_derive2 (const char *type, derive_t v0, derive_t v1, + virDomainPtr dom, const char *devname) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].derive = v0; + values[1].derive = v1; + vl.values = values; + vl.values_len = 2; + + sstrncpy (vl.type, type, sizeof (vl.type)); + sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void submit_derive2 */ + +static int +lv_init (void) +{ + if (virInitialize () != 0) + return -1; + + return 0; +} + +static int +lv_config (const char *key, const char *value) +{ + if (virInitialize () != 0) + return 1; + + if (il_domains == NULL) + il_domains = ignorelist_create (1); + if (il_block_devices == NULL) + il_block_devices = ignorelist_create (1); + if (il_interface_devices == NULL) + il_interface_devices = ignorelist_create (1); + + if (strcasecmp (key, "Connection") == 0) { + char *tmp = strdup (value); + if (tmp == NULL) { + ERROR (PLUGIN_NAME " plugin: Connection strdup failed."); + return 1; + } + sfree (conn_string); + conn_string = tmp; + return 0; + } + + if (strcasecmp (key, "RefreshInterval") == 0) { + char *eptr = NULL; + interval = strtol (value, &eptr, 10); + if (eptr == NULL || *eptr != '\0') return 1; + return 0; + } + + if (strcasecmp (key, "Domain") == 0) { + if (ignorelist_add (il_domains, value)) return 1; + return 0; + } + if (strcasecmp (key, "BlockDevice") == 0) { + if (ignorelist_add (il_block_devices, value)) return 1; + return 0; + } + if (strcasecmp (key, "InterfaceDevice") == 0) { + if (ignorelist_add (il_interface_devices, value)) return 1; + return 0; + } + + if (strcasecmp (key, "IgnoreSelected") == 0) { + if (IS_TRUE (value)) + { + ignorelist_set_invert (il_domains, 0); + ignorelist_set_invert (il_block_devices, 0); + ignorelist_set_invert (il_interface_devices, 0); + } + else + { + ignorelist_set_invert (il_domains, 1); + ignorelist_set_invert (il_block_devices, 1); + ignorelist_set_invert (il_interface_devices, 1); + } + return 0; + } + + if (strcasecmp (key, "HostnameFormat") == 0) { + char *value_copy; + char *fields[HF_MAX_FIELDS]; + int i, n; + + value_copy = strdup (value); + if (value_copy == NULL) { + ERROR (PLUGIN_NAME " plugin: strdup failed."); + return -1; + } + + n = strsplit (value_copy, fields, HF_MAX_FIELDS); + if (n < 1) { + sfree (value_copy); + ERROR (PLUGIN_NAME " plugin: HostnameFormat: no fields"); + return -1; + } + + for (i = 0; i < n; ++i) { + if (strcasecmp (fields[i], "hostname") == 0) + hostname_format[i] = hf_hostname; + else if (strcasecmp (fields[i], "name") == 0) + hostname_format[i] = hf_name; + else if (strcasecmp (fields[i], "uuid") == 0) + hostname_format[i] = hf_uuid; + else { + sfree (value_copy); + ERROR (PLUGIN_NAME " plugin: unknown HostnameFormat field: %s", fields[i]); + return -1; + } + } + sfree (value_copy); + + for (i = n; i < HF_MAX_FIELDS; ++i) + hostname_format[i] = hf_none; + + return 0; + } + + if (strcasecmp (key, "PluginInstanceFormat") == 0) { + char *value_copy; + char *fields[PLGINST_MAX_FIELDS]; + int i, n; + + value_copy = strdup (value); + if (value_copy == NULL) { + ERROR (PLUGIN_NAME " plugin: strdup failed."); + return -1; + } + + n = strsplit (value_copy, fields, PLGINST_MAX_FIELDS); + if (n < 1) { + sfree (value_copy); + ERROR (PLUGIN_NAME " plugin: PluginInstanceFormat: no fields"); + return -1; + } + + for (i = 0; i < n; ++i) { + if (strcasecmp (fields[i], "name") == 0) + plugin_instance_format[i] = plginst_name; + else if (strcasecmp (fields[i], "uuid") == 0) + plugin_instance_format[i] = plginst_uuid; + else { + sfree (value_copy); + ERROR (PLUGIN_NAME " plugin: unknown HostnameFormat field: %s", fields[i]); + return -1; + } + } + sfree (value_copy); + + for (i = n; i < PLGINST_MAX_FIELDS; ++i) + plugin_instance_format[i] = plginst_none; + + return 0; + } + + if (strcasecmp (key, "InterfaceFormat") == 0) { + if (strcasecmp (value, "name") == 0) + interface_format = if_name; + else if (strcasecmp (value, "address") == 0) + interface_format = if_address; + else if (strcasecmp (value, "number") == 0) + interface_format = if_number; + else { + ERROR (PLUGIN_NAME " plugin: unknown InterfaceFormat: %s", value); + return -1; + } + return 0; + } + + /* Unrecognised option. */ + return -1; +} + +static int +lv_read (void) +{ + time_t t; + int i; + + if (conn == NULL) { + /* `conn_string == NULL' is acceptable. */ + conn = virConnectOpenReadOnly (conn_string); + if (conn == NULL) { + c_complain (LOG_ERR, &conn_complain, + PLUGIN_NAME " plugin: Unable to connect: " + "virConnectOpenReadOnly failed."); + return -1; + } + } + c_release (LOG_NOTICE, &conn_complain, + PLUGIN_NAME " plugin: Connection established."); + + time (&t); + + /* Need to refresh domain or device lists? */ + if ((last_refresh == (time_t) 0) || + ((interval > 0) && ((last_refresh + interval) <= t))) { + if (refresh_lists () != 0) { + if (conn != NULL) + virConnectClose (conn); + conn = NULL; + return -1; + } + last_refresh = t; + } + +#if 0 + for (i = 0; i < nr_domains; ++i) + fprintf (stderr, "domain %s\n", virDomainGetName (domains[i])); + for (i = 0; i < nr_block_devices; ++i) + fprintf (stderr, "block device %d %s:%s\n", + i, virDomainGetName (block_devices[i].dom), + block_devices[i].path); + for (i = 0; i < nr_interface_devices; ++i) + fprintf (stderr, "interface device %d %s:%s\n", + i, virDomainGetName (interface_devices[i].dom), + interface_devices[i].path); +#endif + + /* Get CPU usage, memory, VCPU usage for each domain. */ + for (i = 0; i < nr_domains; ++i) { + virDomainInfo info; + virVcpuInfoPtr vinfo = NULL; + virDomainMemoryStatPtr minfo = NULL; + int status; + int j; + + status = virDomainGetInfo (domains[i], &info); + if (status != 0) + { + ERROR (PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", + status); + continue; + } + + if (info.state != VIR_DOMAIN_RUNNING) + { + /* only gather stats for running domains */ + continue; + } + + cpu_submit (info.cpuTime, domains[i], "virt_cpu_total"); + memory_submit ((gauge_t) info.memory * 1024, domains[i]); + + vinfo = malloc (info.nrVirtCpu * sizeof (vinfo[0])); + if (vinfo == NULL) { + ERROR (PLUGIN_NAME " plugin: malloc failed."); + continue; + } + + status = virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu, + /* cpu map = */ NULL, /* cpu map length = */ 0); + if (status < 0) + { + ERROR (PLUGIN_NAME " plugin: virDomainGetVcpus failed with status %i.", + status); + sfree (vinfo); + continue; + } + + for (j = 0; j < info.nrVirtCpu; ++j) + vcpu_submit (vinfo[j].cpuTime, + domains[i], vinfo[j].number, "virt_vcpu"); + + sfree (vinfo); + + minfo = malloc (VIR_DOMAIN_MEMORY_STAT_NR * sizeof (virDomainMemoryStatStruct)); + if (minfo == NULL) { + ERROR ("virt plugin: malloc failed."); + continue; + } + + status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0); + + if (status < 0) { + ERROR ("virt plugin: virDomainMemoryStats failed with status %i.", + status); + sfree (minfo); + continue; + } + + for (j = 0; j < status; j++) { + memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag); + } + + sfree (minfo); + } + + + /* Get block device stats for each domain. */ + for (i = 0; i < nr_block_devices; ++i) { + struct _virDomainBlockStats stats; + + if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path, + &stats, sizeof stats) != 0) + continue; + + if ((stats.rd_req != -1) && (stats.wr_req != -1)) + submit_derive2 ("disk_ops", + (derive_t) stats.rd_req, (derive_t) stats.wr_req, + block_devices[i].dom, block_devices[i].path); + + if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1)) + submit_derive2 ("disk_octets", + (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes, + block_devices[i].dom, block_devices[i].path); + } /* for (nr_block_devices) */ + + /* Get interface stats for each domain. */ + for (i = 0; i < nr_interface_devices; ++i) { + struct _virDomainInterfaceStats stats; + char *display_name = NULL; + + + switch (interface_format) { + case if_address: + display_name = interface_devices[i].address; + break; + case if_number: + display_name = interface_devices[i].number; + break; + case if_name: + default: + display_name = interface_devices[i].path; + } + + if (virDomainInterfaceStats (interface_devices[i].dom, + interface_devices[i].path, + &stats, sizeof stats) != 0) + continue; + + if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1)) + submit_derive2 ("if_octets", + (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes, + interface_devices[i].dom, display_name); + + if ((stats.rx_packets != -1) && (stats.tx_packets != -1)) + submit_derive2 ("if_packets", + (derive_t) stats.rx_packets, (derive_t) stats.tx_packets, + interface_devices[i].dom, display_name); + + if ((stats.rx_errs != -1) && (stats.tx_errs != -1)) + submit_derive2 ("if_errors", + (derive_t) stats.rx_errs, (derive_t) stats.tx_errs, + interface_devices[i].dom, display_name); + + if ((stats.rx_drop != -1) && (stats.tx_drop != -1)) + submit_derive2 ("if_dropped", + (derive_t) stats.rx_drop, (derive_t) stats.tx_drop, + interface_devices[i].dom, display_name); + } /* for (nr_interface_devices) */ + + return 0; +} + +static int +refresh_lists (void) +{ + int n; + + n = virConnectNumOfDomains (conn); + if (n < 0) { + VIRT_ERROR (conn, "reading number of domains"); + return -1; + } + + if (n > 0) { + int i; + int *domids; + + /* Get list of domains. */ + domids = malloc (sizeof (int) * n); + if (domids == 0) { + ERROR (PLUGIN_NAME " plugin: malloc failed."); + return -1; + } + + n = virConnectListDomains (conn, domids, n); + if (n < 0) { + VIRT_ERROR (conn, "reading list of domains"); + sfree (domids); + return -1; + } + + free_block_devices (); + free_interface_devices (); + free_domains (); + + /* Fetch each domain and add it to the list, unless ignore. */ + for (i = 0; i < n; ++i) { + virDomainPtr dom = NULL; + const char *name; + char *xml = NULL; + xmlDocPtr xml_doc = NULL; + xmlXPathContextPtr xpath_ctx = NULL; + xmlXPathObjectPtr xpath_obj = NULL; + int j; + + dom = virDomainLookupByID (conn, domids[i]); + if (dom == NULL) { + VIRT_ERROR (conn, "virDomainLookupByID"); + /* Could be that the domain went away -- ignore it anyway. */ + continue; + } + + name = virDomainGetName (dom); + if (name == NULL) { + VIRT_ERROR (conn, "virDomainGetName"); + goto cont; + } + + if (il_domains && ignorelist_match (il_domains, name) != 0) + goto cont; + + if (add_domain (dom) < 0) { + ERROR (PLUGIN_NAME " plugin: malloc failed."); + goto cont; + } + + /* Get a list of devices for this domain. */ + xml = virDomainGetXMLDesc (dom, 0); + if (!xml) { + VIRT_ERROR (conn, "virDomainGetXMLDesc"); + goto cont; + } + + /* Yuck, XML. Parse out the devices. */ + xml_doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, XML_PARSE_NONET); + if (xml_doc == NULL) { + VIRT_ERROR (conn, "xmlReadDoc"); + goto cont; + } + + xpath_ctx = xmlXPathNewContext (xml_doc); + + /* Block devices. */ + xpath_obj = xmlXPathEval + ((xmlChar *) "/domain/devices/disk/target[@dev]", + xpath_ctx); + if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || + xpath_obj->nodesetval == NULL) + goto cont; + + for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) { + xmlNodePtr node; + char *path = NULL; + + node = xpath_obj->nodesetval->nodeTab[j]; + if (!node) continue; + path = (char *) xmlGetProp (node, (xmlChar *) "dev"); + if (!path) continue; + + if (il_block_devices && + ignore_device_match (il_block_devices, name, path) != 0) + goto cont2; + + add_block_device (dom, path); + cont2: + if (path) xmlFree (path); + } + xmlXPathFreeObject (xpath_obj); + + /* Network interfaces. */ + xpath_obj = xmlXPathEval + ((xmlChar *) "/domain/devices/interface[target[@dev]]", + xpath_ctx); + if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || + xpath_obj->nodesetval == NULL) + goto cont; + + xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval; + + for (j = 0; j < xml_interfaces->nodeNr; ++j) { + char *path = NULL; + char *address = NULL; + xmlNodePtr xml_interface; + + xml_interface = xml_interfaces->nodeTab[j]; + if (!xml_interface) continue; + xmlNodePtr child = NULL; + + for (child = xml_interface->children; child; child = child->next) { + if (child->type != XML_ELEMENT_NODE) continue; + + if (xmlStrEqual(child->name, (const xmlChar *) "target")) { + path = (char *) xmlGetProp (child, (const xmlChar *) "dev"); + if (!path) continue; + } else if (xmlStrEqual(child->name, (const xmlChar *) "mac")) { + address = (char *) xmlGetProp (child, (const xmlChar *) "address"); + if (!address) continue; + } + } + + if (il_interface_devices && + (ignore_device_match (il_interface_devices, name, path) != 0 || + ignore_device_match (il_interface_devices, name, address) != 0)) + goto cont3; + + add_interface_device (dom, path, address, j+1); + cont3: + if (path) xmlFree (path); + if (address) xmlFree (address); + } + + cont: + if (xpath_obj) xmlXPathFreeObject (xpath_obj); + if (xpath_ctx) xmlXPathFreeContext (xpath_ctx); + if (xml_doc) xmlFreeDoc (xml_doc); + sfree (xml); + } + + sfree (domids); + } + + return 0; +} + +static void +free_domains () +{ + int i; + + if (domains) { + for (i = 0; i < nr_domains; ++i) + virDomainFree (domains[i]); + sfree (domains); + } + domains = NULL; + nr_domains = 0; +} + +static int +add_domain (virDomainPtr dom) +{ + virDomainPtr *new_ptr; + int new_size = sizeof (domains[0]) * (nr_domains+1); + + if (domains) + new_ptr = realloc (domains, new_size); + else + new_ptr = malloc (new_size); + + if (new_ptr == NULL) + return -1; + + domains = new_ptr; + domains[nr_domains] = dom; + return nr_domains++; +} + +static void +free_block_devices () +{ + int i; + + if (block_devices) { + for (i = 0; i < nr_block_devices; ++i) + sfree (block_devices[i].path); + sfree (block_devices); + } + block_devices = NULL; + nr_block_devices = 0; +} + +static int +add_block_device (virDomainPtr dom, const char *path) +{ + struct block_device *new_ptr; + int new_size = sizeof (block_devices[0]) * (nr_block_devices+1); + char *path_copy; + + path_copy = strdup (path); + if (!path_copy) + return -1; + + if (block_devices) + new_ptr = realloc (block_devices, new_size); + else + new_ptr = malloc (new_size); + + if (new_ptr == NULL) { + sfree (path_copy); + return -1; + } + block_devices = new_ptr; + block_devices[nr_block_devices].dom = dom; + block_devices[nr_block_devices].path = path_copy; + return nr_block_devices++; +} + +static void +free_interface_devices () +{ + int i; + + if (interface_devices) { + for (i = 0; i < nr_interface_devices; ++i) { + sfree (interface_devices[i].path); + sfree (interface_devices[i].address); + sfree (interface_devices[i].number); + } + sfree (interface_devices); + } + interface_devices = NULL; + nr_interface_devices = 0; +} + +static int +add_interface_device (virDomainPtr dom, const char *path, const char *address, unsigned int number) +{ + struct interface_device *new_ptr; + int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1); + char *path_copy, *address_copy, number_string[15]; + ++ if ((path == NULL) || (address == NULL)) ++ return EINVAL; ++ + path_copy = strdup (path); + if (!path_copy) return -1; + + address_copy = strdup (address); + if (!address_copy) { + sfree(path_copy); + return -1; + } + + snprintf(number_string, sizeof (number_string), "interface-%u", number); + + if (interface_devices) + new_ptr = realloc (interface_devices, new_size); + else + new_ptr = malloc (new_size); + + if (new_ptr == NULL) { + sfree (path_copy); + sfree (address_copy); + return -1; + } + interface_devices = new_ptr; + interface_devices[nr_interface_devices].dom = dom; + interface_devices[nr_interface_devices].path = path_copy; + interface_devices[nr_interface_devices].address = address_copy; + interface_devices[nr_interface_devices].number = strdup(number_string); + return nr_interface_devices++; +} + +static int +ignore_device_match (ignorelist_t *il, const char *domname, const char *devpath) +{ + char *name; + int n, r; + ++ if ((domname == NULL) || (devpath == NULL)) ++ return 0; ++ + n = sizeof (char) * (strlen (domname) + strlen (devpath) + 2); + name = malloc (n); + if (name == NULL) { + ERROR (PLUGIN_NAME " plugin: malloc failed."); + return 0; + } + ssnprintf (name, n, "%s:%s", domname, devpath); + r = ignorelist_match (il, name); + sfree (name); + return r; +} + +static int +lv_shutdown (void) +{ + free_block_devices (); + free_interface_devices (); + free_domains (); + + if (conn != NULL) + virConnectClose (conn); + conn = NULL; + + ignorelist_free (il_domains); + il_domains = NULL; + ignorelist_free (il_block_devices); + il_block_devices = NULL; + ignorelist_free (il_interface_devices); + il_interface_devices = NULL; + + return 0; +} + +void +module_register (void) +{ + plugin_register_config (PLUGIN_NAME, + lv_config, + config_keys, NR_CONFIG_KEYS); + plugin_register_init (PLUGIN_NAME, lv_init); + plugin_register_read (PLUGIN_NAME, lv_read); + plugin_register_shutdown (PLUGIN_NAME, lv_shutdown); +} + +/* + * vim: shiftwidth=4 tabstop=8 softtabstop=4 expandtab fdm=marker + */