[collectd] [PATCH] Add InterfaceFormat setting to libvirt plugin
Ruben Kerkhof
ruben at rubenkerkhof.com
Sun May 30 14:57:18 CEST 2010
Since the interface path changes between reboots of a
virtual machine, each reboot generates a new instance in collectd.
So let's introduce the InterfaceFormat setting
When set to 'address' it uses the mac address of
the interface instead of the path.
Signed-off-by: Ruben Kerkhof <ruben at rubenkerkhof.com>
---
src/collectd.conf.in | 1 +
src/collectd.conf.pod | 8 ++++
src/libvirt.c | 98 +++++++++++++++++++++++++++++++++++++++---------
3 files changed, 88 insertions(+), 19 deletions(-)
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index bf1d7a4..3c94a6f 100644
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@@ -386,6 +386,7 @@
# InterfaceDevice "name:device"
# IgnoreSelected false
# HostnameFormat name
+# InterfaceFormat name
#</Plugin>
#<Plugin madwifi>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 9377686..c70b9e0 100644
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -1563,6 +1563,14 @@ You can also specify combinations of these fields. For example B<name uuid>
means to concatenate the guest name and UUID (with a literal colon character
between, thus I<"foo:1234-1234-1234-1234">).
+=item B<InterfaceFormat> B<name|address|...>
+
+When the libvirt plugin logs interface data, it sets the name of the collected data according to this setting.
+The default is to use the path as provided by the hypervisor (the âdevâ property of the target node), which is equal to setting B<name>.
+
+B<address> means use the interface's mac address.
+This is useful since the interface path might change between reboots of a guest or across migrations.
+
=back
=head2 Plugin C<logfile>
diff --git a/src/libvirt.c b/src/libvirt.c
index bcbf0e6..d97f90a 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -43,6 +43,7 @@ static const char *config_keys[] = {
"IgnoreSelected",
"HostnameFormat",
+ "InterfaceFormat",
NULL
};
@@ -89,13 +90,14 @@ static int add_block_device (virDomainPtr dom, const char *path);
struct interface_device {
virDomainPtr dom; /* domain */
char *path; /* name of interface device */
+ char *address; /* mac address 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);
+static int add_interface_device (virDomainPtr dom, const char *path, const char *address);
/* HostnameFormat. */
#define HF_MAX_FIELDS 3
@@ -110,6 +112,15 @@ enum hf_field {
static enum hf_field hostname_format[HF_MAX_FIELDS] =
{ hf_name };
+/* InterfaceFormat. */
+
+enum if_field {
+ if_address,
+ if_name
+};
+
+static enum if_field interface_format = if_name;
+
/* Time that we last refreshed. */
static time_t last_refresh = (time_t) 0;
@@ -241,6 +252,28 @@ lv_config (const char *key, const char *value)
return 0;
}
+ if (strcasecmp (key, "InterfaceFormat") == 0) {
+ char *value_copy;
+
+ value_copy = strdup (value);
+ if (value_copy == NULL) {
+ ERROR ("libvirt plugin: strdup failed.");
+ return -1;
+ }
+
+ if (strcasecmp (value_copy, "name") == 0)
+ interface_format = if_name;
+ else if (strcasecmp (value_copy, "address") == 0)
+ interface_format = if_address;
+ else {
+ free (value_copy);
+ ERROR ("unknown InterfaceFormat: %s", value_copy);
+ return -1;
+ }
+ free (value_copy);
+ return 0;
+ }
+
/* Unrecognised option. */
return -1;
}
@@ -343,6 +376,10 @@ lv_read (void)
/* Get interface stats for each domain. */
for (i = 0; i < nr_interface_devices; ++i) {
struct _virDomainInterfaceStats stats;
+ char *display_name = interface_devices[i].path;
+
+ if (interface_format == if_address)
+ display_name = interface_devices[i].address;
if (virDomainInterfaceStats (interface_devices[i].dom,
interface_devices[i].path,
@@ -352,22 +389,22 @@ lv_read (void)
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);
+ t, interface_devices[i].dom, display_name);
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);
+ t, interface_devices[i].dom, display_name);
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);
+ t, interface_devices[i].dom, display_name);
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);
+ t, interface_devices[i].dom, display_name);
} /* for (nr_interface_devices) */
return 0;
@@ -482,28 +519,44 @@ refresh_lists (void)
/* Network interfaces. */
xpath_obj = xmlXPathEval
- ((xmlChar *) "/domain/devices/interface/target[@dev]",
+ ((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;
+ xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
+
+ for (j = 0; j < xml_interfaces->nodeNr; ++j) {
char *path = NULL;
+ char *address = NULL;
+ xmlNodePtr xml_interface;
- node = xpath_obj->nodesetval->nodeTab[j];
- if (!node) continue;
- path = (char *) xmlGetProp (node, (xmlChar *) "dev");
- if (!path) continue;
+ 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, path) != 0 ||
+ ignore_device_match (il_interface_devices, name, address) != 0))
goto cont3;
- add_interface_device (dom, path);
- cont3:
- if (path) xmlFree (path);
+ add_interface_device (dom, path, address);
+ cont3:
+ if (path) xmlFree (path);
+ if (address) xmlFree (address);
}
cont:
@@ -598,8 +651,10 @@ free_interface_devices ()
int i;
if (interface_devices) {
- for (i = 0; i < nr_interface_devices; ++i)
+ for (i = 0; i < nr_interface_devices; ++i) {
free (interface_devices[i].path);
+ free (interface_devices[i].address);
+ }
free (interface_devices);
}
interface_devices = NULL;
@@ -607,15 +662,18 @@ free_interface_devices ()
}
static int
-add_interface_device (virDomainPtr dom, const char *path)
+add_interface_device (virDomainPtr dom, const char *path, const char *address)
{
struct interface_device *new_ptr;
int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1);
- char *path_copy;
+ char *path_copy, *address_copy;
path_copy = strdup (path);
if (!path_copy) return -1;
+ address_copy = strdup (address);
+ if (!address_copy) return -1;
+
if (interface_devices)
new_ptr = realloc (interface_devices, new_size);
else
@@ -623,11 +681,13 @@ add_interface_device (virDomainPtr dom, const char *path)
if (new_ptr == NULL) {
free (path_copy);
+ free (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;
return nr_interface_devices++;
}
--
1.6.6.1
More information about the collectd
mailing list