summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ce0fa03)
raw | patch | inline | side by side (parent: ce0fa03)
author | Benjamin Gilbert <bgilbert@cs.cmu.edu> | |
Wed, 16 Apr 2014 19:00:11 +0000 (15:00 -0400) | ||
committer | Benjamin Gilbert <bgilbert@cs.cmu.edu> | |
Wed, 16 Apr 2014 19:36:44 +0000 (15:36 -0400) |
Thin pools and traditional snapshot volumes fill up as I/O is performed
to their associated thin volumes or origins. When they run out of free
space, things break, so it's useful to monitor their disk utilization.
Add new plugin instances for thin pool data LVs, thin pool metadata LVs,
and thick snapshot LVs, each with "used" and "free" type instances.
to their associated thin volumes or origins. When they run out of free
space, things break, so it's useful to monitor their disk utilization.
Add new plugin instances for thin pool data LVs, thin pool metadata LVs,
and thick snapshot LVs, each with "used" and "free" type instances.
AUTHORS | patch | blob | history | |
src/lvm.c | patch | blob | history |
index 31d132fbfa3c12cf27948ab5e1c9019ddab49adc..fa55cc0e875bebca72a68ff799a72c5f88f77306 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
- LPAR plugin.
- Various fixes for AIX, HP-UX and Solaris.
+Benjamin Gilbert <bgilbert at cs.cmu.edu>
+ - Improvements to the LVM plugin.
+
Bert Vermeulen <bert at biot.com>
- sigrok plugin
diff --git a/src/lvm.c b/src/lvm.c
index 1677f0567073339f8a9a065e9bee2b4af8c35d22..97d8017094374114a850cd01f08f2c077817540e 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
/**
* collectd - src/lvm.c
* Copyright (C) 2013 Chad Malfait
+ * Copyright (C) 2014 Carnegie Mellon University
*
* 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
*
* Authors:
* Chad Malfait <malfaitc at yahoo.com>
+ * Benjamin Gilbert <bgilbert at cs.cmu.edu>
**/
#include <lvm2app.h>
#include "common.h"
#include "plugin.h"
+#define NO_VALUE UINT64_MAX
+#define PERCENT_SCALE_FACTOR 1e-8
+
+static uint64_t get_lv_property_int(lv_t lv, char const *property)
+{
+ lvm_property_value_t v;
+
+ v = lvm_lv_get_property(lv, property);
+ if (!v.is_valid || !v.is_integer)
+ return NO_VALUE;
+ /* May be NO_VALUE if @property does not apply to this LV */
+ return v.value.integer;
+}
+
+static char const *get_lv_property_string(lv_t lv, char const *property)
+{
+ lvm_property_value_t v;
+
+ v = lvm_lv_get_property(lv, property);
+ if (!v.is_valid || !v.is_string)
+ return NULL;
+ return v.value.string;
+}
+
static void lvm_submit (char const *plugin_instance, char const *type_instance,
uint64_t ivalue)
{
plugin_dispatch_values (&vl);
}
+static void report_lv_utilization(lv_t lv, char const *vg_name,
+ char const *lv_name, uint64_t lv_size,
+ char const *used_percent_property)
+{
+ uint64_t used_percent_unscaled;
+ uint64_t used_bytes;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
+ used_percent_unscaled = get_lv_property_int(lv, used_percent_property);
+ if (used_percent_unscaled == NO_VALUE)
+ return;
+ used_bytes = lv_size * (used_percent_unscaled * PERCENT_SCALE_FACTOR);
+
+ ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-%s",
+ vg_name, lv_name);
+ lvm_submit(plugin_instance, "used", used_bytes);
+ lvm_submit(plugin_instance, "free", lv_size - used_bytes);
+}
+
+static void report_thin_pool_utilization(lv_t lv, char const *vg_name,
+ uint64_t lv_size)
+{
+ char const *data_lv;
+ char const *metadata_lv;
+ uint64_t metadata_size;
+
+ data_lv = get_lv_property_string(lv, "data_lv");
+ metadata_lv = get_lv_property_string(lv, "metadata_lv");
+ metadata_size = get_lv_property_int(lv, "lv_metadata_size");
+ if (data_lv == NULL || metadata_lv == NULL || metadata_size == NO_VALUE)
+ return;
+
+ report_lv_utilization(lv, vg_name, data_lv, lv_size, "data_percent");
+ report_lv_utilization(lv, vg_name, metadata_lv, metadata_size,
+ "metadata_percent");
+}
+
static void vg_read(vg_t vg, char const *vg_name)
{
struct dm_list *lvs;
struct lvm_lv_list *lvl;
+ char const *name;
char const *attrs;
+ uint64_t size;
lvm_submit (vg_name, "free", lvm_vg_get_free_size(vg));
lvs = lvm_vg_list_lvs(vg);
dm_list_iterate_items(lvl, lvs) {
+ name = lvm_lv_get_name(lvl->lv);
attrs = lvm_lv_get_attr(lvl->lv);
- if (attrs == NULL)
+ size = lvm_lv_get_size(lvl->lv);
+ if (name == NULL || attrs == NULL || size == NO_VALUE)
continue;
+
/* Condition on volume type. We want the reported sizes in the
volume group to sum to the size of the volume group, so we ignore
virtual volumes. */
switch (attrs[0]) {
+ case 's':
+ case 'S':
+ /* Snapshot. Also report used/free space. */
+ report_lv_utilization(lvl->lv, vg_name, name, size,
+ "data_percent");
+ break;
case 't':
/* Thin pool virtual volume. We report the underlying data
- and metadata volumes, not this one. Ignore. */
+ and metadata volumes, not this one. Report used/free
+ space, then ignore. */
+ report_thin_pool_utilization(lvl->lv, vg_name, size);
continue;
case 'v':
/* Virtual volume. Ignore. */
/* Thin volume or thin snapshot. Ignore. */
continue;
}
- lvm_submit(vg_name, lvm_lv_get_name(lvl->lv), lvm_lv_get_size(lvl->lv));
+ lvm_submit(vg_name, name, size);
}
}