plugin_interface="no"
plugin_ipvs="no"
plugin_irq="no"
-plugin_libvirtstats="no"
+plugin_libvirt="no"
plugin_load="no"
plugin_memory="no"
plugin_multimeter="no"
if test "x$with_libxml2" = "xyes" && test "x$with_libvirt" = "xyes"
then
- plugin_libvirtstats="yes"
+ plugin_libvirt="yes"
fi
if test "x$have_getloadavg" = "xyes"
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],[$plugin_libvirtstats], [Virtual machine statistics])
+AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics])
AC_PLUGIN([load], [$plugin_load], [System load])
AC_PLUGIN([logfile], [yes], [File logging plugin])
AC_PLUGIN([mbmon], [yes], [Query mbmond])
iptables . . . . . $enable_iptables
ipvs . . . . . . . $enable_ipvs
irq . . . . . . . . $enable_irq
- libvirtstats . . . $enable_libvirtstats
+ libvirt . . . . . . $enable_libvirt
load . . . . . . . $enable_load
logfile . . . . . . $enable_logfile
mbmon . . . . . . . $enable_mbmon
collectd_DEPENDENCIES += irq.la
endif
-if BUILD_PLUGIN_LIBVIRTSTATS
-pkglib_LTLIBRARIES += libvirtstats.la
-libvirtstats_la_SOURCES = libvirtstats.c
-libvirtstats_la_CFLAGS = $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
-libvirtstats_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
-libvirtstats_la_LDFLAGS = -module -avoid-version
-collectd_LDADD += "-dlopen" libvirtstats.la
-collectd_DEPENDENCIES += libvirtstats.la
+if BUILD_PLUGIN_LIBVIRT
+pkglib_LTLIBRARIES += libvirt.la
+libvirt_la_SOURCES = libvirt.c
+libvirt_la_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
--- /dev/null
+/**
+ * collectd - src/libvirt.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@redhat.com>
+ **/
+
+#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>
+
+static const char *config_keys[] = {
+ "Connection",
+
+ "RefreshInterval",
+
+ "Domain",
+ "BlockDevice",
+ "InterfaceDevice",
+ "IgnoreSelected",
+
+ "HostnameFormat",
+
+ 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);
+
+/* 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 };
+
+/* 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,
+ virDomainPtr dom, const char *type);
+static void vcpu_submit (unsigned long long cpu_time,
+ time_t t,
+ virDomainPtr dom, int vcpu_nr, const char *type);
+static void submit_counter2 (const char *type, counter_t v0, counter_t v1,
+ time_t t,
+ virDomainPtr dom, const char *devname);
+
+/* 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
+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) {
+ 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);
+ }
+ 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 ("libvirt plugin: strdup failed.");
+ return -1;
+ }
+
+ n = strsplit (value_copy, fields, HF_MAX_FIELDS);
+ if (n < 1) {
+ free (value_copy);
+ ERROR ("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 {
+ free (value_copy);
+ ERROR ("unknown HostnameFormat field: %s", fields[i]);
+ return -1;
+ }
+ }
+ free (value_copy);
+
+ for (i = n; i < HF_MAX_FIELDS; ++i)
+ hostname_format[i] = hf_none;
+
+ return 0;
+ }
+
+ /* Unrecognised option. */
+ return -1;
+}
+
+static int
+lv_read (void)
+{
+ time_t t;
+ int i;
+
+ if (conn == NULL) {
+ ERROR ("libvirt plugin: 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 () != 0)
+ 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, VCPU usage for each domain. */
+ for (i = 0; i < nr_domains; ++i) {
+ virDomainInfo info;
+ virVcpuInfoPtr vinfo = NULL;
+ int j;
+
+ if (virDomainGetInfo (domains[i], &info) != 0)
+ continue;
+
+ cpu_submit (info.cpuTime, t, domains[i], "virt_cpu_total");
+
+ vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]);
+ if (vinfo == NULL) {
+ ERROR ("libvirt plugin: malloc failed.");
+ continue;
+ }
+
+ if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
+ NULL, 0) != 0) {
+ free (vinfo);
+ continue;
+ }
+
+ for (j = 0; j < info.nrVirtCpu; ++j)
+ vcpu_submit (vinfo[j].cpuTime,
+ t, domains[i], vinfo[j].number, "virt_vcpu");
+
+ free (vinfo);
+ }
+
+ /* 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_counter2 ("disk_ops",
+ (counter_t) stats.rd_req, (counter_t) stats.wr_req,
+ t, block_devices[i].dom, block_devices[i].path);
+
+ if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1))
+ submit_counter2 ("disk_octets",
+ (counter_t) stats.rd_bytes, (counter_t) stats.wr_bytes,
+ t, 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;
+
+ 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_counter2 ("if_octets",
+ (counter_t) stats.rx_bytes, (counter_t) stats.tx_bytes,
+ t, interface_devices[i].dom, interface_devices[i].path);
+
+ if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
+ submit_counter2 ("if_packets",
+ (counter_t) stats.rx_packets, (counter_t) stats.tx_packets,
+ t, interface_devices[i].dom, interface_devices[i].path);
+
+ if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
+ submit_counter2 ("if_errors",
+ (counter_t) stats.rx_errs, (counter_t) stats.tx_errs,
+ t, interface_devices[i].dom, interface_devices[i].path);
+
+ if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
+ submit_counter2 ("if_dropped",
+ (counter_t) stats.rx_drop, (counter_t) stats.tx_drop,
+ t, interface_devices[i].dom, interface_devices[i].path);
+ } /* 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 ("libvirt plugin: malloc failed.");
+ return -1;
+ }
+
+ n = virConnectListDomains (conn, domids, n);
+ if (n < 0) {
+ 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 (add_domain (dom) < 0) {
+ ERROR ("libvirt 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;
+
+ 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_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);
+ }
+
+ 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 ("libvirt plugin: malloc failed.");
+ return 0;
+ }
+ snprintf (name, n, "%s:%s", domname, devpath);
+ r = ignorelist_match (il, name);
+ free (name);
+ return r;
+}
+
+static void
+init_value_list (value_list_t *vl, time_t t, virDomainPtr dom)
+{
+ int i;
+ char *host_ptr;
+ size_t host_len;
+
+ vl->time = t;
+ vl->interval = interval_g;
+
+ strncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
+ vl->plugin[sizeof (vl->plugin) - 1] = '\0';
+
+ vl->host[0] = '\0';
+ host_ptr = vl->host;
+ host_len = sizeof (vl->host);
+
+ /* Construct the hostname field according to HostnameFormat. */
+ for (i = 0; i < HF_MAX_FIELDS; ++i) {
+ int status = 0;
+
+ switch (hostname_format[i]) {
+ case hf_none:
+ /* do nothing */
+ break;
+
+ case hf_hostname:
+ status = snprintf (host_ptr, host_len, ":%s", hostname_g);
+ break;
+
+ case hf_name:
+ {
+ const char *name = virDomainGetName (dom);
+ if (name != NULL)
+ status = snprintf (host_ptr, host_len, ":%s", name);
+ break;
+ }
+ case hf_uuid:
+ {
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ if (virDomainGetUUIDString (dom, uuid) == 0) {
+ uuid[sizeof (uuid) - 1] = '\0';
+ status = snprintf (host_ptr, host_len, ":%s", uuid);
+ }
+ break;
+ }
+ } /* switch (hostname_format[i]) */
+
+ /* If status >= host_len
+ * => the buffer is full, there's no null-byte at the end and
+ * continuing with this loop doesn't make any sense. */
+ if (status >= host_len) {
+ host_len = 0;
+ host_ptr = NULL;
+ }
+ /* else: Test if anything was added to the buffer */
+ else if (status > 0) {
+ host_len -= status;
+ host_ptr += status;
+ }
+
+ if (host_len <= 0)
+ break;
+ } /* for (i) */
+
+ vl->host[sizeof (vl->host) - 1] = '\0';
+} /* void init_value_list */
+
+static void
+cpu_submit (unsigned long long cpu_time,
+ time_t t,
+ virDomainPtr dom, const char *type)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ init_value_list (&vl, t, dom);
+
+ values[0].counter = cpu_time;
+
+ vl.values = values;
+ vl.values_len = 1;
+
+ plugin_dispatch_values (type, &vl);
+}
+
+static void
+vcpu_submit (counter_t cpu_time,
+ time_t t,
+ virDomainPtr dom, int vcpu_nr, const char *type)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ init_value_list (&vl, t, dom);
+
+ values[0].counter = cpu_time;
+ vl.values = values;
+ vl.values_len = 1;
+
+ snprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
+ vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+
+ plugin_dispatch_values (type, &vl);
+}
+
+static void
+submit_counter2 (const char *type, counter_t v0, counter_t v1,
+ time_t t,
+ virDomainPtr dom, const char *devname)
+{
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ init_value_list (&vl, t, dom);
+
+ values[0].counter = v0;
+ values[1].counter = v1;
+ vl.values = values;
+ vl.values_len = 2;
+
+ strncpy (vl.type_instance, devname, sizeof (vl.type_instance));
+ vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter2 */
+
+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 ("libvirt",
+ lv_config,
+ config_keys, NR_CONFIG_KEYS);
+ plugin_register_init ("libvirt", lv_init);
+ plugin_register_read ("libvirt", lv_read);
+ plugin_register_shutdown ("libvirt", lv_shutdown);
+}
+
+/*
+ * vim: shiftwidth=4 tabstop=8 softtabstop=4 expandtab fdm=marker
+ */
+++ /dev/null
-/**
- * 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@redhat.com>
- **/
-
-#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>
-
-static const char *config_keys[] = {
- "Connection",
-
- "RefreshInterval",
-
- "Domain",
- "BlockDevice",
- "InterfaceDevice",
- "IgnoreSelected",
-
- "HostnameFormat",
-
- 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);
-
-/* 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 };
-
-/* 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,
- virDomainPtr dom, const char *type);
-static void vcpu_submit (unsigned long long cpu_time,
- time_t t,
- virDomainPtr dom, int vcpu_nr, const char *type);
-static void submit_counter2 (const char *type, counter_t v0, counter_t v1,
- time_t t,
- virDomainPtr dom, const char *devname);
-
-/* 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 () != 0)
- return -1;
-
- return 0;
-}
-
-static int
-libvirtstats_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) {
- 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);
- }
- 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 ("libvirtstats plugin: strdup failed.");
- return -1;
- }
-
- n = strsplit (value_copy, fields, HF_MAX_FIELDS);
- if (n < 1) {
- free (value_copy);
- ERROR ("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 {
- free (value_copy);
- ERROR ("unknown HostnameFormat field: %s", fields[i]);
- return -1;
- }
- }
- free (value_copy);
-
- for (i = n; i < HF_MAX_FIELDS; ++i)
- hostname_format[i] = hf_none;
-
- return 0;
- }
-
- /* Unrecognised option. */
- return -1;
-}
-
-static int
-libvirtstats_read (void)
-{
- time_t t;
- int i;
-
- if (conn == NULL) {
- ERROR ("libvirtstats plugin: 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 () != 0)
- 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, VCPU usage for each domain. */
- for (i = 0; i < nr_domains; ++i) {
- virDomainInfo info;
- virVcpuInfoPtr vinfo = NULL;
- int j;
-
- if (virDomainGetInfo (domains[i], &info) != 0)
- continue;
-
- cpu_submit (info.cpuTime, t, domains[i], "virt_cpu_total");
-
- vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]);
- if (vinfo == NULL) {
- ERROR ("libvirtstats plugin: malloc failed.");
- continue;
- }
-
- if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
- NULL, 0) != 0) {
- free (vinfo);
- continue;
- }
-
- for (j = 0; j < info.nrVirtCpu; ++j)
- vcpu_submit (vinfo[j].cpuTime,
- t, domains[i], vinfo[j].number, "virt_vcpu");
-
- free (vinfo);
- }
-
- /* 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_counter2 ("disk_ops",
- (counter_t) stats.rd_req, (counter_t) stats.wr_req,
- t, block_devices[i].dom, block_devices[i].path);
-
- if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1))
- submit_counter2 ("disk_octets",
- (counter_t) stats.rd_bytes, (counter_t) stats.wr_bytes,
- t, 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;
-
- 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_counter2 ("if_octets",
- (counter_t) stats.rx_bytes, (counter_t) stats.tx_bytes,
- t, interface_devices[i].dom, interface_devices[i].path);
-
- if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
- submit_counter2 ("if_packets",
- (counter_t) stats.rx_packets, (counter_t) stats.tx_packets,
- t, interface_devices[i].dom, interface_devices[i].path);
-
- if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
- submit_counter2 ("if_errors",
- (counter_t) stats.rx_errs, (counter_t) stats.tx_errs,
- t, interface_devices[i].dom, interface_devices[i].path);
-
- if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
- submit_counter2 ("if_dropped",
- (counter_t) stats.rx_drop, (counter_t) stats.tx_drop,
- t, interface_devices[i].dom, interface_devices[i].path);
- } /* 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 ("libvirtstats plugin: malloc failed.");
- return -1;
- }
-
- n = virConnectListDomains (conn, domids, n);
- if (n < 0) {
- 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 (add_domain (dom) < 0) {
- ERROR ("libvirtstats 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;
-
- 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_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);
- }
-
- 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 ("libvirtstats plugin: malloc failed.");
- return 0;
- }
- snprintf (name, n, "%s:%s", domname, devpath);
- r = ignorelist_match (il, name);
- free (name);
- return r;
-}
-
-static void
-init_value_list (value_list_t *vl, time_t t, virDomainPtr dom)
-{
- int i;
- char *host_ptr;
- size_t host_len;
-
- vl->time = t;
- vl->interval = interval_g;
-
- strncpy (vl->plugin, "libvirtstats", sizeof (vl->plugin));
- vl->plugin[sizeof (vl->plugin) - 1] = '\0';
-
- vl->host[0] = '\0';
- host_ptr = vl->host;
- host_len = sizeof (vl->host);
-
- /* Construct the hostname field according to HostnameFormat. */
- for (i = 0; i < HF_MAX_FIELDS; ++i) {
- int status = 0;
-
- switch (hostname_format[i]) {
- case hf_none:
- /* do nothing */
- break;
-
- case hf_hostname:
- status = snprintf (host_ptr, host_len, ":%s", hostname_g);
- break;
-
- case hf_name:
- {
- const char *name = virDomainGetName (dom);
- if (name != NULL)
- status = snprintf (host_ptr, host_len, ":%s", name);
- break;
- }
- case hf_uuid:
- {
- char uuid[VIR_UUID_STRING_BUFLEN];
- if (virDomainGetUUIDString (dom, uuid) == 0) {
- uuid[sizeof (uuid) - 1] = '\0';
- status = snprintf (host_ptr, host_len, ":%s", uuid);
- }
- break;
- }
- } /* switch (hostname_format[i]) */
-
- /* If status >= host_len
- * => the buffer is full, there's no null-byte at the end and
- * continuing with this loop doesn't make any sense. */
- if (status >= host_len) {
- host_len = 0;
- host_ptr = NULL;
- }
- /* else: Test if anything was added to the buffer */
- else if (status > 0) {
- host_len -= status;
- host_ptr += status;
- }
-
- if (host_len <= 0)
- break;
- } /* for (i) */
-
- vl->host[sizeof (vl->host) - 1] = '\0';
-} /* void init_value_list */
-
-static void
-cpu_submit (unsigned long long cpu_time,
- time_t t,
- virDomainPtr dom, const char *type)
-{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
-
- init_value_list (&vl, t, dom);
-
- values[0].counter = cpu_time;
-
- vl.values = values;
- vl.values_len = 1;
-
- plugin_dispatch_values (type, &vl);
-}
-
-static void
-vcpu_submit (counter_t cpu_time,
- time_t t,
- virDomainPtr dom, int vcpu_nr, const char *type)
-{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
-
- init_value_list (&vl, t, dom);
-
- values[0].counter = cpu_time;
- vl.values = values;
- vl.values_len = 1;
-
- snprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-
- plugin_dispatch_values (type, &vl);
-}
-
-static void
-submit_counter2 (const char *type, counter_t v0, counter_t v1,
- time_t t,
- virDomainPtr dom, const char *devname)
-{
- value_t values[2];
- value_list_t vl = VALUE_LIST_INIT;
-
- init_value_list (&vl, t, dom);
-
- values[0].counter = v0;
- values[1].counter = v1;
- vl.values = values;
- vl.values_len = 2;
-
- strncpy (vl.type_instance, devname, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-
- plugin_dispatch_values (type, &vl);
-} /* void submit_counter2 */
-
-static int
-libvirtstats_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 ("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: shiftwidth=4 tabstop=8 softtabstop=4 expandtab fdm=marker
- */