Firstly just to say that this is a patch against the released collectd 4.2.0. I need to pull out the GIT repository and rebase the patch against that. Any other comments, most welcome!
Usage -----With this patch you should be able to collect stats by adding the following to your collectd.conf file:
LoadPlugin libvirtstats <Plugin libvirtstats> Connection "xen:///" </Plugin>'collectd' only needs to be running on the host. It uses libvirt to collect stats for each guest, via mechanisms in the hypervisor or host operating system.
Requirements ------------libvirt >= 0.3.3 and libxml2. The configure file should auto-detect the requirements and configure libvirtstats plugin only if they are available.
Problems --------I can't seem to get the ignorelist to do anything at all. It seems like it includes all the domains and devices, no matter what I specify in the configuration file and what the state of IgnoreSelected is set to.
In the types.db, I have set the max for virt_cpu_total to be 256,000,000,000. The max CPU usage for a single CPU is 1 billion nanoseconds per second, but virt_cpu_total is for all CPUs in the system, and there could be (in theory) an unlimited number of CPUs, so an unlimited max. Therefore I have assumed here that max CPUs = 256.
I'm using CSV output, which works, but it seems to report the aggregate counter values instead of the differences. Is that to be expected?
Rich. -- Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/ Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 03798903
Only in collectd-4.2.0-libvirt: aclocal.m4 diff -ur collectd-4.2.0/AUTHORS collectd-4.2.0-libvirt/AUTHORS --- collectd-4.2.0/AUTHORS 2007-10-27 10:04:58.000000000 +0100 +++ collectd-4.2.0-libvirt/AUTHORS 2007-10-31 10:47:36.000000000 +0000 @@ -60,6 +60,9 @@ contributed by: LuboÅ¡ StanÄ?k <lubek at users.sourceforge.net> +Libvirt integration by: + Richard Jones <rjones@xxxxxxxxxx> + collectd is available at: <http://collectd.org/> Only in collectd-4.2.0-libvirt: autom4te.cache Only in collectd-4.2.0-libvirt/bindings: Makefile Only in collectd-4.2.0-libvirt/bindings: Makefile.in Only in collectd-4.2.0-libvirt/bindings/perl: blib Only in collectd-4.2.0-libvirt/bindings/perl/Collectd: Makefile Only in collectd-4.2.0-libvirt/bindings/perl/Collectd: pm_to_blib Only in collectd-4.2.0-libvirt/bindings/perl: Makefile Only in collectd-4.2.0-libvirt/bindings/perl: pm_to_blib Only in collectd-4.2.0-libvirt: config.log Only in collectd-4.2.0-libvirt: config.status Only in collectd-4.2.0-libvirt: configure diff -ur collectd-4.2.0/configure.in collectd-4.2.0-libvirt/configure.in --- collectd-4.2.0/configure.in 2007-10-27 10:15:13.000000000 +0100 +++ collectd-4.2.0-libvirt/configure.in 2007-11-01 16:34:36.000000000 +0000 @@ -1598,6 +1598,30 @@ fi AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes") +dnl Check for libvirt and libxml2 libraries. +AC_CHECK_LIB(xml2,xmlXPathEval, + [with_libxml2="yes"], + [with_libxml2="no"]) + +with_libvirt="no" +if test "x$with_libxml2" = "xyes"; then + AC_CHECK_LIB(virt,virDomainBlockStats, + [with_libvirt="yes"], + [with_libvirt="no (symbol virDomainBlockStats not found)"]) +fi +dnl Add the right compiler flags and libraries. +if test "x$with_libvirt" = "xyes"; then + PKG_PROG_PKG_CONFIG + if test "x$PKG_CONFIG" != "x"; then + BUILD_WITH_LIBVIRTSTATS_CFLAGS="`pkg-config --cflags libvirt` `pkg-config --cflags libxml-2.0`" + BUILD_WITH_LIBVIRTSTATS_LIBS="`pkg-config --libs libvirt` `pkg-config --libs libxml-2.0`" + AC_SUBST(BUILD_WITH_LIBVIRTSTATS_CFLAGS) + AC_SUBST(BUILD_WITH_LIBVIRTSTATS_LIBS) + fi +fi + +dnl End of check for libvirt and libxml2 libraries. + # Check for enabled/disabled features # @@ -1859,6 +1883,7 @@ AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters]) AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics]) AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics]) +AC_PLUGIN([libvirtstats],[$with_libvirt], [Virtual machine statistics]) AC_PLUGIN([load], [$plugin_load], [System load]) AC_PLUGIN([logfile], [yes], [File logging plugin]) AC_PLUGIN([mbmon], [yes], [Query mbmond]) @@ -1957,6 +1982,8 @@ libsensors . . . . $with_lm_sensors libstatgrab . . . . $with_libstatgrab libupsclient . . . $with_libupsclient + libvirt . . . . . . $with_libvirt + libxml2 . . . . . . $with_libxml2 libxmms . . . . . . $with_libxmms Features: @@ -1985,6 +2012,7 @@ iptables . . . . . $enable_iptables ipvs . . . . . . . $enable_ipvs irq . . . . . . . . $enable_irq + libvirtstats . . . $enable_libvirtstats load . . . . . . . $enable_load logfile . . . . . . $enable_logfile mbmon . . . . . . . $enable_mbmon Only in collectd-4.2.0-libvirt/libltdl: aclocal.m4 Only in collectd-4.2.0-libvirt/libltdl: autom4te.cache Only in collectd-4.2.0-libvirt/libltdl: config.h Only in collectd-4.2.0-libvirt/libltdl: config.log Only in collectd-4.2.0-libvirt/libltdl: config.status Only in collectd-4.2.0-libvirt/libltdl: configure Only in collectd-4.2.0-libvirt/libltdl: libltdlc.la Only in collectd-4.2.0-libvirt/libltdl: .libs Only in collectd-4.2.0-libvirt/libltdl: libtool Only in collectd-4.2.0-libvirt/libltdl: ltdl.lo Only in collectd-4.2.0-libvirt/libltdl: ltdl.o Only in collectd-4.2.0-libvirt/libltdl: Makefile Only in collectd-4.2.0-libvirt/libltdl: Makefile.in Only in collectd-4.2.0-libvirt/libltdl: stamp-h1 Only in collectd-4.2.0-libvirt: libtool Only in collectd-4.2.0-libvirt: Makefile Only in collectd-4.2.0-libvirt: Makefile.in diff -ur collectd-4.2.0/README collectd-4.2.0-libvirt/README --- collectd-4.2.0/README 2007-10-27 10:09:25.000000000 +0100 +++ collectd-4.2.0-libvirt/README 2007-10-31 17:43:19.000000000 +0000 @@ -80,6 +80,9 @@ - load System load average over the last 1, 5 and 15 minutes. + - libvirt + CPU, disk and network I/O statistics from virtual machines. + - mbmon Motherboard sensors: temperature, fanspeed and voltage information, using mbmon(1). @@ -324,6 +327,9 @@ For compiling on Darwin in general and the `apple_sensors' plugin in particular. + * libvirt (optional) + Collect statistics from virtual machines. + Configuring / Compiling / Installing ------------------------------------ Only in collectd-4.2.0-libvirt/src: apache.la Only in collectd-4.2.0-libvirt/src: apache_la-apache.lo Only in collectd-4.2.0-libvirt/src: apcups.la Only in collectd-4.2.0-libvirt/src: apcups.lo Only in collectd-4.2.0-libvirt/src: battery.la Only in collectd-4.2.0-libvirt/src: battery.lo Only in collectd-4.2.0-libvirt/src: collectd Only in collectd-4.2.0-libvirt/src: collectd-collectd.o Only in collectd-4.2.0-libvirt/src: collectd-common.o Only in collectd-4.2.0-libvirt/src: collectd.conf Only in collectd-4.2.0-libvirt/src: collectd-configfile.o Only in collectd-4.2.0-libvirt/src: collectd-nagios Only in collectd-4.2.0-libvirt/src: collectd-nagios.o Only in collectd-4.2.0-libvirt/src: collectd-plugin.o Only in collectd-4.2.0-libvirt/src: collectd-types_list.o Only in collectd-4.2.0-libvirt/src: collectd-utils_avltree.o Only in collectd-4.2.0-libvirt/src: collectd-utils_ignorelist.o Only in collectd-4.2.0-libvirt/src: collectd-utils_llist.o Only in collectd-4.2.0-libvirt/src: collectd-utils_mount.o Only in collectd-4.2.0-libvirt/src: config.h diff -ur collectd-4.2.0/src/config.h.in collectd-4.2.0-libvirt/src/config.h.in --- collectd-4.2.0/src/config.h.in 2007-10-27 10:18:32.000000000 +0100 +++ collectd-4.2.0-libvirt/src/config.h.in 2007-11-05 13:38:20.000000000 +0000 @@ -418,6 +418,9 @@ /* Define to 1 if the irq plugin is enabled. */ #undef HAVE_PLUGIN_IRQ +/* Define to 1 if the libvirtstats plugin is enabled. */ +#undef HAVE_PLUGIN_LIBVIRTSTATS + /* Define to 1 if the load plugin is enabled. */ #undef HAVE_PLUGIN_LOAD Only in collectd-4.2.0-libvirt/src: cpufreq.la Only in collectd-4.2.0-libvirt/src: cpufreq.lo Only in collectd-4.2.0-libvirt/src: cpu.la Only in collectd-4.2.0-libvirt/src: cpu.lo Only in collectd-4.2.0-libvirt/src: csv.la Only in collectd-4.2.0-libvirt/src: csv.lo Only in collectd-4.2.0-libvirt/src: .deps Only in collectd-4.2.0-libvirt/src: df.la Only in collectd-4.2.0-libvirt/src: df.lo Only in collectd-4.2.0-libvirt/src: disk.la Only in collectd-4.2.0-libvirt/src: disk.lo Only in collectd-4.2.0-libvirt/src: email.la Only in collectd-4.2.0-libvirt/src: email.lo Only in collectd-4.2.0-libvirt/src: entropy.la Only in collectd-4.2.0-libvirt/src: entropy.lo Only in collectd-4.2.0-libvirt/src: exec.la Only in collectd-4.2.0-libvirt/src: exec.lo Only in collectd-4.2.0-libvirt/src: hddtemp.la Only in collectd-4.2.0-libvirt/src: hddtemp.lo Only in collectd-4.2.0-libvirt/src: interface.la Only in collectd-4.2.0-libvirt/src: interface.lo Only in collectd-4.2.0-libvirt/src: irq.la Only in collectd-4.2.0-libvirt/src: irq.lo Only in collectd-4.2.0-libvirt/src/liboconfig: liboconfig.la Only in collectd-4.2.0-libvirt/src/liboconfig: .libs Only in collectd-4.2.0-libvirt/src/liboconfig: Makefile Only in collectd-4.2.0-libvirt/src/liboconfig: Makefile.in Only in collectd-4.2.0-libvirt/src/liboconfig: oconfig.lo Only in collectd-4.2.0-libvirt/src/liboconfig: parser.lo Only in collectd-4.2.0-libvirt/src/liboconfig: scanner.lo Only in collectd-4.2.0-libvirt/src/liboping: liboping.la Only in collectd-4.2.0-libvirt/src/liboping: liboping.lo Only in collectd-4.2.0-libvirt/src/liboping: .libs Only in collectd-4.2.0-libvirt/src/liboping: Makefile Only in collectd-4.2.0-libvirt/src/liboping: Makefile.in Only in collectd-4.2.0-libvirt/src: .libs diff -ur collectd-4.2.0/src/libvirtstats.c collectd-4.2.0-libvirt/src/libvirtstats.c --- collectd-4.2.0/src/libvirtstats.c 2007-11-05 13:30:45.000000000 +0000 +++ collectd-4.2.0-libvirt/src/libvirtstats.c 2007-11-05 13:46:00.000000000 +0000 @@ -0,0 +1,743 @@ +/** + * collectd - src/libvirtstats.c + * Copyright (C) 2006,2007 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 <rjones@xxxxxxxxxx> + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "configfile.h" +#include "utils_ignorelist.h" + +#include <libvirt/libvirt.h> +#include <libvirt/virterror.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> + +#define LIBVIRTSTATS_DEBUG 1 + +static const char *config_keys[] = { + "Connection", + + "RefreshInterval", + + "Domain", + "BlockDevice", + "InterfaceDevice", + "IgnoreSelected", + NULL +}; +#define NR_CONFIG_KEYS ((sizeof config_keys / sizeof config_keys[0]) - 1) + +/* Connection. */ +static virConnectPtr conn = 0; + +/* 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 */ +}; + +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); + +/* Time that we last refreshed. */ +static time_t last_refresh = (time_t) 0; + +static int refresh_lists (void); + +/* Submit functions. */ +static void cpu_submit (unsigned long long cpu_time, + time_t t, + const char *domname, const char *type); +static void vcpu_submit (unsigned long long cpu_time, + time_t t, + const char *domname, int vcpu_nr, const char *type); +static void disk_submit (long long read, long long write, + time_t t, + const char *domname, const char *devname, + const char *type); +static void if_submit (long long rx, long long tx, + time_t t, + const char *domname, const char *devname, + const char *type); + +/* 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 int +libvirtstats_init (void) +{ + if (virInitialize () == -1) + return -1; + + il_domains = ignorelist_create (0); + il_block_devices = ignorelist_create (0); + il_interface_devices = ignorelist_create (0); + + return 0; +} + +static int +libvirtstats_config (const char *key, const char *value) +{ + if (virInitialize () == -1) + return 1; + + if (strcasecmp (key, "Connection") == 0) { + if (conn != 0) { + ERROR ("Connection may only be given once in config file"); + return 1; + } + conn = virConnectOpenReadOnly (value); + if (!conn) { + VIRT_ERROR (NULL, "connection failed"); + return 1; + } + 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 (strcasecmp (value, "True") == 0 || + strcasecmp (value, "Yes") == 0 || + strcasecmp (value, "On") == 0) + { + 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); + } + } + + /* Unrecognised option. */ + return -1; +} + +static int +libvirtstats_read (void) +{ + time_t t; + int i; + + if (conn == NULL) { + ERROR ("Not connected. Use Connection in config file to supply connection URI. For more information see http://libvirt.org/uri.html"); + return -1; + } + + time (&t); + + /* Need to refresh domain or device lists? */ + if (last_refresh == (time_t) 0 || + (interval > 0 && last_refresh + interval <= t)) { + if (refresh_lists () == -1) return -1; + last_refresh = t; + } + +#if LIBVIRTSTATS_DEBUG + 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, VCPU usage for each domain. */ + for (i = 0; i < nr_domains; ++i) { + const char *name; + virDomainInfo info; + virVcpuInfoPtr vinfo = NULL; + int j; + + name = virDomainGetName (domains[i]); + if (name == NULL) continue; + + if (virDomainGetInfo (domains[i], &info) == -1) continue; + + cpu_submit (info.cpuTime, t, name, "virt_cpu_total"); + + vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]); + if (vinfo == NULL) { + ERROR ("malloc: %s", strerror (errno)); + continue; + } + + if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu, + NULL, 0) == -1) { + free (vinfo); + continue; + } + + for (j = 0; j < info.nrVirtCpu; ++j) + vcpu_submit (vinfo[j].cpuTime, + t, name, vinfo[j].number, "virt_vcpu"); + + free (vinfo); + } + + /* Get block device stats for each domain. */ + for (i = 0; i < nr_block_devices; ++i) { + const char *name; + struct _virDomainBlockStats stats; + + name = virDomainGetName (block_devices[i].dom); + if (name == NULL) continue; + + if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path, + &stats, sizeof stats) == -1) + continue; + + disk_submit (stats.rd_req, stats.wr_req, + t, name, block_devices[i].path, + "disk_ops"); + disk_submit (stats.rd_bytes, stats.wr_bytes, + t, name, block_devices[i].path, + "disk_octets"); + } + + /* Get interface stats for each domain. */ + for (i = 0; i < nr_interface_devices; ++i) { + const char *name; + struct _virDomainInterfaceStats stats; + + name = virDomainGetName (interface_devices[i].dom); + if (name == NULL) continue; + + if (virDomainInterfaceStats (interface_devices[i].dom, + interface_devices[i].path, + &stats, sizeof stats) == -1) + continue; + + if_submit (stats.rx_bytes, stats.tx_bytes, + t, name, interface_devices[i].path, + "if_octets"); + if_submit (stats.rx_packets, stats.tx_packets, + t, name, interface_devices[i].path, + "if_packets"); + if_submit (stats.rx_errs, stats.tx_errs, + t, name, interface_devices[i].path, + "if_errors"); + if_submit (stats.rx_drop, stats.tx_drop, + t, name, interface_devices[i].path, + "if_dropped"); + } + + return 0; +} + +static int +refresh_lists (void) +{ + int n; + +#if LIBVIRTSTATS_DEBUG + fprintf (stderr, "libvirtstats: refresh_lists called\n"); +#endif + + n = virConnectNumOfDomains (conn); + if (n == -1) { + 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 ("malloc failed: %s", strerror (errno)); + return -1; + } + + n = virConnectListDomains (conn, domids, n); + if (n == -1) { + VIRT_ERROR (conn, "reading list of domains"); + free (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 LIBVIRTSTATS_DEBUG + fprintf (stderr, "name = %s\n", name); +#endif + + if (add_domain (dom) == -1) { + ERROR ("malloc: %s", strerror (errno)); + 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 LIBVIRTSTATS_DEBUG + fprintf (stderr, "node = %p\n", node); +#endif + if (!node) continue; + path = (char *) xmlGetProp (node, (xmlChar *) "dev"); +#if LIBVIRTSTATS_DEBUG + xmlElemDump (stderr, xml_doc, node); + fprintf (stderr, "\npath = %s\n", path); +#endif + 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; + + for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) { + xmlNodePtr node; + char *path = NULL; + + node = xpath_obj->nodesetval->nodeTab[j]; +#if LIBVIRTSTATS_DEBUG + fprintf (stderr, "node = %p\n", node); +#endif + if (!node) continue; + path = (char *) xmlGetProp (node, (xmlChar *) "dev"); +#if LIBVIRTSTATS_DEBUG + xmlElemDump (stderr, xml_doc, node); + fprintf (stderr, "\npath = %s\n", path); +#endif + if (!path) continue; + + if (il_interface_devices && + ignore_device_match (il_interface_devices, name, path) != 0) + goto cont3; + + add_interface_device (dom, path); + cont3: + if (path) xmlFree (path); + } + + cont: + if (xpath_obj) xmlXPathFreeObject (xpath_obj); + if (xpath_ctx) xmlXPathFreeContext (xpath_ctx); + if (xml_doc) xmlFreeDoc (xml_doc); + if (xml) free (xml); + } + + free (domids); + } + +#if LIBVIRTSTATS_DEBUG + fprintf (stderr, "libvirtstats: refresh_lists finished OK\n"); +#endif + + return 0; +} + +static void +free_domains () +{ + int i; + + if (domains) { + for (i = 0; i < nr_domains; ++i) + virDomainFree (domains[i]); + free (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) + free (block_devices[i].path); + free (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) { + free (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) + free (interface_devices[i].path); + free (interface_devices); + } + interface_devices = NULL; + nr_interface_devices = 0; +} + +static int +add_interface_device (virDomainPtr dom, const char *path) +{ + struct interface_device *new_ptr; + int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1); + char *path_copy; + + path_copy = strdup (path); + if (!path_copy) return -1; + + if (interface_devices) + new_ptr = realloc (interface_devices, new_size); + else + new_ptr = malloc (new_size); + + if (new_ptr == NULL) { + free (path_copy); + return -1; + } + interface_devices = new_ptr; + interface_devices[nr_interface_devices].dom = dom; + interface_devices[nr_interface_devices].path = path_copy; + return nr_interface_devices++; +} + +static int +ignore_device_match (ignorelist_t *il, const char *domname, const char *devpath) +{ + char *name; + int n, r; + + n = sizeof (char) * (strlen (domname) + strlen (devpath) + 2); + name = malloc (n); + if (name == NULL) { + ERROR ("malloc: %s", strerror (errno)); + return 0; + } + snprintf (name, n, "%s:%s", domname, devpath); + r = ignorelist_match (il, name); + free (name); + return r; +} + +static void +cpu_submit (unsigned long long cpu_time, + time_t t, + const char *domname, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = cpu_time; + + vl.values = values; + vl.values_len = 1; + vl.time = t; + vl.interval = interval_g; + strncpy (vl.plugin, "libvirtstats", DATA_MAX_NAME_LEN); + strncpy (vl.host, domname, DATA_MAX_NAME_LEN); + /*strncpy (vl.type_instance, ?, DATA_MAX_NAME_LEN);*/ + + plugin_dispatch_values (type, &vl); +} + +static void +vcpu_submit (unsigned long long cpu_time, + time_t t, + const char *domname, int vcpu_nr, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = cpu_time; + + vl.values = values; + vl.values_len = 1; + vl.time = t; + vl.interval = interval_g; + strncpy (vl.plugin, "libvirtstats", DATA_MAX_NAME_LEN); + strncpy (vl.host, domname, DATA_MAX_NAME_LEN); + snprintf (vl.type_instance, DATA_MAX_NAME_LEN, "%d", vcpu_nr); + + plugin_dispatch_values (type, &vl); +} + +static void +disk_submit (long long read, long long write, + time_t t, + const char *domname, const char *devname, + const char *type) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = read >= 0 ? (unsigned long long) read : 0; + values[1].counter = write >= 0 ? (unsigned long long) write : 0; + + vl.values = values; + vl.values_len = 2; + vl.time = t; + vl.interval = interval_g; + strncpy (vl.plugin, "libvirtstats", DATA_MAX_NAME_LEN); + strncpy (vl.host, domname, DATA_MAX_NAME_LEN); + strncpy (vl.type_instance, devname, DATA_MAX_NAME_LEN); + + plugin_dispatch_values (type, &vl); +} + +static void +if_submit (long long rx, long long tx, + time_t t, + const char *domname, const char *devname, + const char *type) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + values[0].counter = rx >= 0 ? (unsigned long long) rx : 0; + values[1].counter = tx >= 0 ? (unsigned long long) tx : 0; + + vl.values = values; + vl.values_len = 2; + vl.time = t; + vl.interval = interval_g; + strncpy (vl.plugin, "libvirtstats", DATA_MAX_NAME_LEN); + strncpy (vl.host, domname, DATA_MAX_NAME_LEN); + strncpy (vl.type_instance, devname, DATA_MAX_NAME_LEN); + + plugin_dispatch_values (type, &vl); +} + +static int +libvirtstats_shutdown (void) +{ + free_block_devices (); + free_interface_devices (); + free_domains (); + + 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; + + if (conn) virConnectClose (conn); + conn = NULL; + + return 0; +} + +void +module_register (void) +{ + plugin_register_config ("libvirtstats", + libvirtstats_config, + config_keys, NR_CONFIG_KEYS); + plugin_register_init ("libvirtstats", libvirtstats_init); + plugin_register_read ("libvirtstats", libvirtstats_read); + plugin_register_shutdown ("libvirtstats", libvirtstats_shutdown); +} + +/* + * vim: set tabstop=4: + * vim: set shiftwidth=4: + * vim: set expandtab: + */ +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ Only in collectd-4.2.0-libvirt/src: libvirtstats.la Only in collectd-4.2.0-libvirt/src: libvirtstats_la-libvirtstats.lo Only in collectd-4.2.0-libvirt/src: libvirtstats.loT Only in collectd-4.2.0-libvirt/src: load.la Only in collectd-4.2.0-libvirt/src: load.lo Only in collectd-4.2.0-libvirt/src: logfile.la Only in collectd-4.2.0-libvirt/src: logfile.lo Only in collectd-4.2.0-libvirt/src: Makefile diff -ur collectd-4.2.0/src/Makefile.am collectd-4.2.0-libvirt/src/Makefile.am --- collectd-4.2.0/src/Makefile.am 2007-10-27 10:04:59.000000000 +0100 +++ collectd-4.2.0-libvirt/src/Makefile.am 2007-11-05 13:09:01.000000000 +0000 @@ -276,6 +276,16 @@ collectd_DEPENDENCIES += irq.la endif +if BUILD_PLUGIN_LIBVIRTSTATS +pkglib_LTLIBRARIES += libvirtstats.la +libvirtstats_la_SOURCES = libvirtstats.c +libvirtstats_la_CFLAGS = $(BUILD_WITH_LIBVIRTSTATS_CFLAGS) -Wall -Werror +libvirtstats_la_LIBADD = $(BUILD_WITH_LIBVIRTSTATS_LIBS) +libvirtstats_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" libvirtstats.la +collectd_DEPENDENCIES += libvirtstats.la +endif + if BUILD_PLUGIN_LOAD pkglib_LTLIBRARIES += load.la load_la_SOURCES = load.c Only in collectd-4.2.0-libvirt/src: Makefile.in Only in collectd-4.2.0-libvirt/src: mbmon.la Only in collectd-4.2.0-libvirt/src: mbmon.lo Only in collectd-4.2.0-libvirt/src: memcached.la Only in collectd-4.2.0-libvirt/src: memcached_la-memcached.lo Only in collectd-4.2.0-libvirt/src: memory.la Only in collectd-4.2.0-libvirt/src: memory.lo Only in collectd-4.2.0-libvirt/src: multimeter.la Only in collectd-4.2.0-libvirt/src: multimeter.lo Only in collectd-4.2.0-libvirt/src: network.la Only in collectd-4.2.0-libvirt/src: network.lo Only in collectd-4.2.0-libvirt/src: nfs.la Only in collectd-4.2.0-libvirt/src: nfs.lo Only in collectd-4.2.0-libvirt/src: nginx.la Only in collectd-4.2.0-libvirt/src: nginx.lo Only in collectd-4.2.0-libvirt/src: ntpd.la Only in collectd-4.2.0-libvirt/src: ntpd.lo Only in collectd-4.2.0-libvirt/src: perl.la Only in collectd-4.2.0-libvirt/src: perl_la-perl.lo Only in collectd-4.2.0-libvirt/src: ping.la Only in collectd-4.2.0-libvirt/src: ping.lo Only in collectd-4.2.0-libvirt/src: processes.la Only in collectd-4.2.0-libvirt/src: processes.lo Only in collectd-4.2.0-libvirt/src: serial.la Only in collectd-4.2.0-libvirt/src: serial.lo Only in collectd-4.2.0-libvirt/src: stamp-h1 Only in collectd-4.2.0-libvirt/src: swap.la Only in collectd-4.2.0-libvirt/src: swap.lo Only in collectd-4.2.0-libvirt/src: syslog.la Only in collectd-4.2.0-libvirt/src: syslog.lo Only in collectd-4.2.0-libvirt/src: tcpconns.la Only in collectd-4.2.0-libvirt/src: tcpconns.lo diff -ur collectd-4.2.0/src/types.db collectd-4.2.0-libvirt/src/types.db --- collectd-4.2.0/src/types.db 2007-10-27 10:04:59.000000000 +0100 +++ collectd-4.2.0-libvirt/src/types.db 2007-11-05 13:34:35.000000000 +0000 @@ -73,6 +73,8 @@ serial_octets rx:COUNTER:0:4294967295, tx:COUNTER:0:4294967295 swap value:GAUGE:0:1099511627776 users users:GAUGE:0:65535 +virt_cpu_total ns:COUNTER:0:256000000000 +virt_vcpu ns:COUNTER:0:1000000000 vs_threads value:GAUGE:0:65535 vs_processes value:GAUGE:0:65535 vs_memory value:GAUGE:0:9223372036854775807 Only in collectd-4.2.0-libvirt/src: unixsock.la Only in collectd-4.2.0-libvirt/src: unixsock_la-unixsock.lo Only in collectd-4.2.0-libvirt/src: unixsock_la-utils_cmd_putval.lo Only in collectd-4.2.0-libvirt/src: users.la Only in collectd-4.2.0-libvirt/src: users.lo Only in collectd-4.2.0-libvirt/src: utils_cmd_putval.lo Only in collectd-4.2.0-libvirt/src: vserver.la Only in collectd-4.2.0-libvirt/src: vserver.lo Only in collectd-4.2.0-libvirt/src: wireless.la Only in collectd-4.2.0-libvirt/src: wireless.lo Only in collectd-4.2.0-libvirt: ylwrap
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list