summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 096b099)
raw | patch | inline | side by side (parent: 096b099)
author | Sebastian Harl <sh@tokkee.org> | |
Fri, 25 Jan 2013 13:59:23 +0000 (14:59 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Fri, 25 Jan 2013 13:59:23 +0000 (14:59 +0100) |
If enabled, the plugin collects the used space and the number of used files
based on qtree quotas. The interval at which those information is collected
may be configured.
based on qtree quotas. The interval at which those information is collected
may be configured.
src/collectd.conf.pod | patch | blob | history | |
src/netapp.c | patch | blob | history |
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 9fac6a6e037c422e72759a41e8ac79e19e4e0bba..023c376d2c652dfc94652e3fb68b14682ef12dce 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
IgnoreSelectedSnapshot false
</VolumeUsage>
+ <Quota>
+ Interval 60
+ </Quota>
+
<Snapvault>
Interval 30
</Snapvault>
=back
+=head3 The Quota block
+
+This will collect (tree) quota statistics (used disk space and number of used
+files). This mechanism is useful to get usage information for single qtrees.
+In case the quotas are not used for any other purpose, an entry similar to the
+following in C</etc/quotas> would be sufficient:
+
+ /vol/volA/some_qtree tree - - - - -
+
+After adding the entry, issue C<quota on -w volA> on the NetApp filer.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect SnapVault(R) statistics every I<Seconds> seconds.
+
+=back
+
=head3 The SnapVault block
This will collect statistics about the time and traffic of SnapVault(R)
diff --git a/src/netapp.c b/src/netapp.c
index c87960d99a680b119dbeba1e9719f510a3a15205..13aea1e03cd57dca871f0f40aad5089b233331a8 100644 (file)
--- a/src/netapp.c
+++ b/src/netapp.c
} cfg_volume_usage_t;
/* }}} cfg_volume_usage_t */
+/*! Data types for quota statistics {{{
+ *
+ * \brief Persistent data for quota statistics
+ */
+typedef struct {
+ cna_interval_t interval;
+ na_elem_t *query;
+} cfg_quota_t;
+/* }}} cfg_quota_t */
+
/*! Data types for SnapVault statistics {{{
*
* \brief Persistent data for SnapVault(R) statistics
cfg_disk_t *cfg_disk;
cfg_volume_perf_t *cfg_volume_perf;
cfg_volume_usage_t *cfg_volume_usage;
+ cfg_quota_t *cfg_quota;
cfg_snapvault_t *cfg_snapvault;
cfg_system_t *cfg_system;
sfree (cvu);
} /* }}} void free_cfg_volume_usage */
+static void free_cfg_quota (cfg_quota_t *q) /* {{{ */
+{
+ if (q == NULL)
+ return;
+
+ if (q->query != NULL)
+ na_elem_free (q->query);
+
+ sfree (q);
+} /* }}} void free_cfg_quota */
+
static void free_cfg_snapvault (cfg_snapvault_t *sv) /* {{{ */
{
if (sv == NULL)
free_cfg_wafl (hc->cfg_wafl);
free_cfg_volume_perf (hc->cfg_volume_perf);
free_cfg_volume_usage (hc->cfg_volume_usage);
+ free_cfg_quota (hc->cfg_quota);
free_cfg_snapvault (hc->cfg_snapvault);
free_cfg_system (hc->cfg_system);
return (status);
} /* }}} int cna_query_volume_usage */
+/* Data corresponding to <Quota /> */
+static int cna_handle_quota_data (const host_config_t *host, /* {{{ */
+ cfg_quota_t *cfg_quota, na_elem_t *data)
+{
+ na_elem_t *elem_quota;
+ na_elem_t *elem_quotas;
+ na_elem_iter_t iter_quota;
+
+ elem_quotas = na_elem_child (data, "quotas");
+ if (elem_quotas == NULL)
+ {
+ ERROR ("netapp plugin: cna_handle_quota_data: "
+ "na_elem_child (\"quotas\") failed "
+ "for host %s.", host->name);
+ return (-1);
+ }
+
+ iter_quota = na_child_iterator (elem_quotas);
+ for (elem_quota = na_iterator_next (&iter_quota);
+ elem_quota != NULL;
+ elem_quota = na_iterator_next (&iter_quota))
+ {
+ const char *quota_type, *volume_name, *tree_name;
+ uint64_t value;
+
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
+ quota_type = na_child_get_string (elem_quota, "quota-type");
+ if (quota_type == NULL)
+ continue;
+
+ /* possible TODO: support other types as well */
+ if (strcmp (quota_type, "tree") != 0)
+ continue;
+
+ tree_name = na_child_get_string (elem_quota, "tree");
+ if ((tree_name == NULL) || (*tree_name == '\0'))
+ continue;
+
+ volume_name = na_child_get_string (elem_quota, "volume");
+ if (volume_name == NULL)
+ continue;
+
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
+ "quota-%s-%s", volume_name, tree_name);
+
+ value = na_child_get_uint64 (elem_quota, "disk-used", UINT64_MAX);
+ if (value != UINT64_MAX) {
+ value *= 1024; /* disk-used reports kilobytes */
+ submit_double (host->name, plugin_instance,
+ /* type = */ "df_complex", /* type instance = */ NULL,
+ (double)value, /* timestamp = */ 0, host->interval);
+ }
+
+ value = na_child_get_uint64 (elem_quota, "files-used", UINT64_MAX);
+ if (value != UINT64_MAX) {
+ submit_double (host->name, plugin_instance,
+ /* type = */ "files", /* type instance = */ NULL,
+ (double)value, /* timestamp = */ 0, host->interval);
+ }
+ } /* for (elem_quota) */
+
+ return (0);
+} /* }}} int cna_handle_volume_usage_data */
+
+static int cna_setup_quota (cfg_quota_t *cq) /* {{{ */
+{
+ if (cq == NULL)
+ return (EINVAL);
+
+ if (cq->query != NULL)
+ return (0);
+
+ cq->query = na_elem_new ("quota-report");
+ if (cq->query == NULL)
+ {
+ ERROR ("netapp plugin: na_elem_new failed.");
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cna_setup_quota */
+
+static int cna_query_quota (host_config_t *host) /* {{{ */
+{
+ na_elem_t *data;
+ int status;
+ cdtime_t now;
+
+ if (host == NULL)
+ return (EINVAL);
+
+ /* If the user did not configure quota statistics, return without
+ * doing anything. */
+ if (host->cfg_quota == NULL)
+ return (0);
+
+ now = cdtime ();
+ if ((host->cfg_quota->interval.interval + host->cfg_quota->interval.last_read) > now)
+ return (0);
+
+ status = cna_setup_quota (host->cfg_quota);
+ if (status != 0)
+ return (status);
+ assert (host->cfg_quota->query != NULL);
+
+ data = na_server_invoke_elem (host->srv, host->cfg_quota->query);
+ if (na_results_status (data) != NA_OK)
+ {
+ ERROR ("netapp plugin: cna_query_quota: na_server_invoke_elem failed for host %s: %s",
+ host->name, na_results_reason (data));
+ na_elem_free (data);
+ return (-1);
+ }
+
+ status = cna_handle_quota_data (host, host->cfg_quota, data);
+
+ if (status == 0)
+ host->cfg_quota->interval.last_read = now;
+
+ na_elem_free (data);
+ return (status);
+} /* }}} int cna_query_quota */
+
/* Data corresponding to <SnapVault /> */
static int cna_handle_snapvault_data (const char *hostname, /* {{{ */
cfg_snapvault_t *cfg_snapvault, na_elem_t *data, cdtime_t interval)
@@ -2365,6 +2512,40 @@ static void cna_config_volume_usage_default (cfg_volume_usage_t *cvu, /* {{{ */
ignorelist_set_invert (il, /* invert = */ 1);
} /* }}} void cna_config_volume_usage_default */
+/* Corresponds to a <Quota /> block */
+static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
+{
+ cfg_quota_t *cfg_quota;
+ int i;
+
+ if ((host == NULL) || (ci == NULL))
+ return (EINVAL);
+
+ if (host->cfg_quota == NULL)
+ {
+ cfg_quota = malloc (sizeof (*cfg_quota));
+ if (cfg_quota == NULL)
+ return (ENOMEM);
+ memset (cfg_quota, 0, sizeof (*cfg_quota));
+ cfg_quota->query = NULL;
+
+ host->cfg_quota = cfg_quota;
+ }
+ cfg_quota = host->cfg_quota;
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *item = ci->children + i;
+
+ if (strcasecmp (item->key, "Interval") == 0)
+ cna_config_get_interval (item, &cfg_quota->interval);
+ else
+ WARNING ("netapp plugin: The option %s is not allowed within "
+ "`Quota' blocks.", item->key);
+ }
+
+ return (0);
+} /* }}} int cna_config_quota */
+
/* Corresponds to a <Disks /> block */
static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
cfg_disk_t *cfg_disk;
host->cfg_disk = NULL;
host->cfg_volume_perf = NULL;
host->cfg_volume_usage = NULL;
+ host->cfg_quota = NULL;
host->cfg_snapvault = NULL;
host->cfg_system = NULL;
cna_config_volume_performance(host, item);
} else if (!strcasecmp(item->key, "VolumeUsage")) {
cna_config_volume_usage(host, item);
+ } else if (!strcasecmp(item->key, "Quota")) {
+ cna_config_quota(host, item);
} else if (!strcasecmp(item->key, "SnapVault")) {
cna_config_snapvault(host, item);
} else if (!strcasecmp(item->key, "System")) {
if (status != 0)
return (status);
+ status = cna_query_quota (host);
+ if (status != 0)
+ return (status);
+
status = cna_query_snapvault (host);
if (status != 0)
return (status);