/**
* collectd - src/netapp.c
- * Copyright (C) 2009 Sven Trenkel
+ * Copyright (C) 2009,2010 Sven Trenkel
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
} cfg_volume_usage_t;
/* }}} cfg_volume_usage_t */
+/*! Data types for SnapVault statistics {{{
+ *
+ * \brief Persistent data for SnapVault(R) statistics
+ */
+typedef struct {
+ cna_interval_t interval;
+ na_elem_t *query;
+} cfg_snapvault_t;
+/* }}} cfg_snapvault_t */
+
/*! Data types for system statistics {{{
*
* \brief Persistent data for system performance counters
cfg_disk_t *cfg_disk;
cfg_volume_perf_t *cfg_volume_perf;
cfg_volume_usage_t *cfg_volume_usage;
+ cfg_snapvault_t *cfg_snapvault;
cfg_system_t *cfg_system;
struct host_config_s *next;
sfree (cvu);
} /* }}} void free_cfg_volume_usage */
+static void free_cfg_snapvault (cfg_snapvault_t *sv) /* {{{ */
+{
+ if (sv == NULL)
+ return;
+
+ if (sv->query != NULL)
+ na_elem_free (sv->query);
+
+ sfree (sv);
+} /* }}} void free_cfg_snapvault */
+
static void free_cfg_system (cfg_system_t *cs) /* {{{ */
{
if (cs == 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_snapvault (hc->cfg_snapvault);
free_cfg_system (hc->cfg_system);
if (hc->srv != NULL)
return (plugin_dispatch_values (&vl));
} /* }}} int submit_uint64 */
-static int submit_two_counters (const char *host, const char *plugin_inst, /* {{{ */
- const char *type, const char *type_inst, counter_t val0, counter_t val1,
+static int submit_two_derive (const char *host, const char *plugin_inst, /* {{{ */
+ const char *type, const char *type_inst, derive_t val0, derive_t val1,
cdtime_t timestamp, cdtime_t interval)
{
value_t values[2];
- values[0].counter = val0;
- values[1].counter = val1;
+ values[0].derive = val0;
+ values[1].derive = val1;
return (submit_values (host, plugin_inst, type, type_inst,
values, 2, timestamp, interval));
-} /* }}} int submit_two_counters */
+} /* }}} int submit_two_derive */
-static int submit_counter (const char *host, const char *plugin_inst, /* {{{ */
- const char *type, const char *type_inst, counter_t counter,
+static int submit_derive (const char *host, const char *plugin_inst, /* {{{ */
+ const char *type, const char *type_inst, derive_t counter,
cdtime_t timestamp, cdtime_t interval)
{
value_t v;
- v.counter = counter;
+ v.derive = counter;
return (submit_values (host, plugin_inst, type, type_inst,
&v, 1, timestamp, interval));
-} /* }}} int submit_counter */
+} /* }}} int submit_derive */
static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */
const char *type, const char *type_inst, gauge_t val0, gauge_t val1,
if (HAS_ALL_FLAGS (old_data->flags, CFG_VOLUME_PERF_IO)
&& HAS_ALL_FLAGS (new_data->flags, HAVE_VOLUME_PERF_BYTES_READ | HAVE_VOLUME_PERF_BYTES_WRITE))
{
- submit_two_counters (hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
- (counter_t) new_data->read_bytes, (counter_t) new_data->write_bytes, new_data->timestamp, interval);
+ submit_two_derive (hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
+ (derive_t) new_data->read_bytes, (derive_t) new_data->write_bytes, new_data->timestamp, interval);
}
/* Check for and submit disk-operations values */
if (HAS_ALL_FLAGS (old_data->flags, CFG_VOLUME_PERF_OPS)
&& HAS_ALL_FLAGS (new_data->flags, HAVE_VOLUME_PERF_OPS_READ | HAVE_VOLUME_PERF_OPS_WRITE))
{
- submit_two_counters (hostname, plugin_instance, "disk_ops", /* type instance = */ NULL,
- (counter_t) new_data->read_ops, (counter_t) new_data->write_ops, new_data->timestamp, interval);
+ submit_two_derive (hostname, plugin_instance, "disk_ops", /* type instance = */ NULL,
+ (derive_t) new_data->read_ops, (derive_t) new_data->write_ops, new_data->timestamp, interval);
}
/* Check for, calculate and submit disk-latency values */
if (sis == NULL)
continue;
+ if (na_elem_child(sis, "sis-info"))
+ sis = na_elem_child(sis, "sis-info");
+
sis_state = na_child_get_string(sis, "state");
if (sis_state == NULL)
continue;
return (status);
} /* }}} int cna_query_volume_usage */
+/* 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)
+{
+ na_elem_t *status;
+ na_elem_iter_t status_iter;
+
+ status = na_elem_child (data, "status-list");
+ if (! status) {
+ ERROR ("netapp plugin: SnapVault status record missing status-list");
+ return (0);
+ }
+
+ status_iter = na_child_iterator (status);
+ for (status = na_iterator_next (&status_iter);
+ status != NULL;
+ status = na_iterator_next (&status_iter))
+ {
+ const char *dest_sys, *dest_path, *src_sys, *src_path;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ uint64_t value;
+
+ dest_sys = na_child_get_string (status, "destination-system");
+ dest_path = na_child_get_string (status, "destination-path");
+ src_sys = na_child_get_string (status, "source-system");
+ src_path = na_child_get_string (status, "source-path");
+
+ if ((! dest_sys) || (! dest_path) || (! src_sys) || (! src_path))
+ continue;
+
+ value = na_child_get_uint64 (status, "lag-time", UINT64_MAX);
+ if (value == UINT64_MAX) /* no successful baseline transfer yet */
+ continue;
+
+ /* possible TODO: make plugin instance configurable */
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
+ "snapvault-%s", dest_path);
+ submit_double (hostname, plugin_instance, /* type = */ "delay", NULL,
+ (double)value, /* timestamp = */ 0, interval);
+
+ value = na_child_get_uint64 (status, "last-transfer-duration", UINT64_MAX);
+ if (value != UINT64_MAX)
+ submit_double (hostname, plugin_instance, /* type = */ "duration", "last_transfer",
+ (double)value, /* timestamp = */ 0, interval);
+
+ value = na_child_get_uint64 (status, "transfer-progress", UINT64_MAX);
+ if (value == UINT64_MAX)
+ value = na_child_get_uint64 (status, "last-transfer-size", UINT64_MAX);
+ if (value != UINT64_MAX) {
+ value *= 1024; /* this is kilobytes */
+ submit_derive (hostname, plugin_instance, /* type = */ "if_rx_octets", "transferred",
+ value, /* timestamp = */ 0, interval);
+ }
+ } /* for (status) */
+
+ return (0);
+} /* }}} int cna_handle_snapvault_data */
+
+static int cna_handle_snapvault_iter (host_config_t *host, /* {{{ */
+ na_elem_t *data)
+{
+ const char *tag;
+
+ uint32_t records_count;
+ uint32_t i;
+
+ records_count = na_child_get_uint32 (data, "records", UINT32_MAX);
+ if (records_count == UINT32_MAX)
+ return 0;
+
+ tag = na_child_get_string (data, "tag");
+ if (! tag)
+ return 0;
+
+ DEBUG ("netapp plugin: Iterating %u SV records (tag = %s)", records_count, tag);
+
+ for (i = 0; i < records_count; ++i) {
+ na_elem_t *elem;
+
+ elem = na_server_invoke (host->srv,
+ "snapvault-secondary-relationship-status-list-iter-next",
+ "maximum", "1", "tag", tag, NULL);
+
+ if (na_results_status (elem) != NA_OK)
+ {
+ ERROR ("netapp plugin: cna_handle_snapvault_iter: "
+ "na_server_invoke failed for host %s: %s",
+ host->name, na_results_reason (data));
+ na_elem_free (elem);
+ return (-1);
+ }
+
+ cna_handle_snapvault_data (host->name, host->cfg_snapvault, elem, host->interval);
+ na_elem_free (elem);
+ }
+
+ na_elem_free (na_server_invoke (host->srv,
+ "snapvault-secondary-relationship-status-list-iter-end",
+ "tag", tag, NULL));
+ return (0);
+} /* }}} int cna_handle_snapvault_iter */
+
+static int cna_setup_snapvault (cfg_snapvault_t *sv) /* {{{ */
+{
+ if (sv == NULL)
+ return (EINVAL);
+
+ if (sv->query != NULL)
+ return (0);
+
+ sv->query = na_elem_new ("snapvault-secondary-relationship-status-list-iter-start");
+ if (sv->query == NULL)
+ {
+ ERROR ("netapp plugin: na_elem_new failed.");
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cna_setup_snapvault */
+
+static int cna_query_snapvault (host_config_t *host) /* {{{ */
+{
+ na_elem_t *data;
+ int status;
+ cdtime_t now;
+
+ if (host == NULL)
+ return EINVAL;
+
+ if (host->cfg_snapvault == NULL)
+ return 0;
+
+ now = cdtime ();
+ if ((host->cfg_snapvault->interval.interval + host->cfg_snapvault->interval.last_read) > now)
+ return (0);
+
+ status = cna_setup_snapvault (host->cfg_snapvault);
+ if (status != 0)
+ return (status);
+ assert (host->cfg_snapvault->query != NULL);
+
+ data = na_server_invoke_elem (host->srv, host->cfg_snapvault->query);
+ if (na_results_status (data) != NA_OK)
+ {
+ ERROR ("netapp plugin: cna_query_snapvault: na_server_invoke_elem failed for host %s: %s",
+ host->name, na_results_reason (data));
+ na_elem_free (data);
+ return (-1);
+ }
+
+ status = cna_handle_snapvault_iter (host, data);
+
+ if (status == 0)
+ host->cfg_snapvault->interval.last_read = now;
+
+ na_elem_free (data);
+ return (status);
+} /* }}} int cna_query_snapvault */
+
/* Data corresponding to <System /> */
static int cna_handle_system_data (const char *hostname, /* {{{ */
cfg_system_t *cfg_system, na_elem_t *data, int interval)
na_elem_t *counter;
na_elem_iter_t counter_iter;
- counter_t disk_read = 0, disk_written = 0;
- counter_t net_recv = 0, net_sent = 0;
- counter_t cpu_busy = 0, cpu_total = 0;
+ derive_t disk_read = 0, disk_written = 0;
+ derive_t net_recv = 0, net_sent = 0;
+ derive_t cpu_busy = 0, cpu_total = 0;
uint32_t counter_flags = 0;
const char *instance;
continue;
if (!strcmp(name, "disk_data_read")) {
- disk_read = (counter_t) (value * 1024);
+ disk_read = (derive_t) (value * 1024);
counter_flags |= 0x01;
} else if (!strcmp(name, "disk_data_written")) {
- disk_written = (counter_t) (value * 1024);
+ disk_written = (derive_t) (value * 1024);
counter_flags |= 0x02;
} else if (!strcmp(name, "net_data_recv")) {
- net_recv = (counter_t) (value * 1024);
+ net_recv = (derive_t) (value * 1024);
counter_flags |= 0x04;
} else if (!strcmp(name, "net_data_sent")) {
- net_sent = (counter_t) (value * 1024);
+ net_sent = (derive_t) (value * 1024);
counter_flags |= 0x08;
} else if (!strcmp(name, "cpu_busy")) {
- cpu_busy = (counter_t) value;
+ cpu_busy = (derive_t) value;
counter_flags |= 0x10;
} else if (!strcmp(name, "cpu_elapsed_time")) {
- cpu_total = (counter_t) value;
+ cpu_total = (derive_t) value;
counter_flags |= 0x20;
} else if ((cfg_system->flags & CFG_SYSTEM_OPS)
&& (value > 0) && (strlen(name) > 4)
&& (!strcmp(name + strlen(name) - 4, "_ops"))) {
- submit_counter (hostname, instance, "disk_ops_complex", name,
- (counter_t) value, timestamp, interval);
+ submit_derive (hostname, instance, "disk_ops_complex", name,
+ (derive_t) value, timestamp, interval);
}
} /* for (counter) */
if ((cfg_system->flags & CFG_SYSTEM_DISK)
&& (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
- submit_two_counters (hostname, instance, "disk_octets", NULL,
+ submit_two_derive (hostname, instance, "disk_octets", NULL,
disk_read, disk_written, timestamp, interval);
if ((cfg_system->flags & CFG_SYSTEM_NET)
&& (HAS_ALL_FLAGS (counter_flags, 0x04 | 0x08)))
- submit_two_counters (hostname, instance, "if_octets", NULL,
+ submit_two_derive (hostname, instance, "if_octets", NULL,
net_recv, net_sent, timestamp, interval);
if ((cfg_system->flags & CFG_SYSTEM_CPU)
&& (HAS_ALL_FLAGS (counter_flags, 0x10 | 0x20)))
{
- submit_counter (hostname, instance, "cpu", "system",
+ submit_derive (hostname, instance, "cpu", "system",
cpu_busy, timestamp, interval);
- submit_counter (hostname, instance, "cpu", "idle",
+ submit_derive (hostname, instance, "cpu", "idle",
cpu_total - cpu_busy, timestamp, interval);
}
return (0);
} /* }}} int cna_config_volume_usage */
+/* Corresponds to a <SnapVault /> block */
+static int cna_config_snapvault (host_config_t *host, /* {{{ */
+ const oconfig_item_t *ci)
+{
+ cfg_snapvault_t *cfg_snapvault;
+ int i;
+
+ if ((host == NULL) || (ci == NULL))
+ return EINVAL;
+
+ if (host->cfg_snapvault == NULL)
+ {
+ cfg_snapvault = malloc (sizeof (*cfg_snapvault));
+ if (cfg_snapvault == NULL)
+ return ENOMEM;
+ memset (cfg_snapvault, 0, sizeof (*cfg_snapvault));
+ cfg_snapvault->query = NULL;
+
+ host->cfg_snapvault = cfg_snapvault;
+ }
+
+ cfg_snapvault = host->cfg_snapvault;
+
+ 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_snapvault->interval);
+ else
+ WARNING ("netapp plugin: The option %s is not allowed within "
+ "`SnapVault' blocks.", item->key);
+ }
+
+ return 0;
+} /* }}} int cna_config_snapvault */
+
/* Corresponds to a <System /> block */
static int cna_config_system (host_config_t *host, /* {{{ */
oconfig_item_t *ci)
host->cfg_disk = NULL;
host->cfg_volume_perf = NULL;
host->cfg_volume_usage = NULL;
+ host->cfg_snapvault = NULL;
host->cfg_system = NULL;
status = cf_util_get_string (ci, &host->name);
cna_config_volume_performance(host, item);
} else if (!strcasecmp(item->key, "VolumeUsage")) {
cna_config_volume_usage(host, item);
+ } else if (!strcasecmp(item->key, "SnapVault")) {
+ cna_config_snapvault(host, item);
} else if (!strcasecmp(item->key, "System")) {
cna_config_system(host, item);
} else {
na_server_adminuser(host->srv, host->username, host->password);
na_server_set_timeout(host->srv, 5 /* seconds */);
- return 0;
+ return (0);
} /* }}} int cna_init_host */
static int cna_init (void) /* {{{ */
return (0);
} /* }}} cna_init */
+static int cna_read_internal (host_config_t *host) { /* {{{ */
+ int status;
+
+ status = cna_query_wafl (host);
+ if (status != 0)
+ return (status);
+
+ status = cna_query_disk (host);
+ if (status != 0)
+ return (status);
+
+ status = cna_query_volume_perf (host);
+ if (status != 0)
+ return (status);
+
+ status = cna_query_volume_usage (host);
+ if (status != 0)
+ return (status);
+
+ status = cna_query_snapvault (host);
+ if (status != 0)
+ return (status);
+
+ status = cna_query_system (host);
+ if (status != 0)
+ return (status);
+
+ return 0;
+} /* }}} int cna_read_internal */
+
static int cna_read (user_data_t *ud) { /* {{{ */
host_config_t *host;
int status;
status = cna_init_host (host);
if (status != 0)
return (status);
-
- cna_query_wafl (host);
- cna_query_disk (host);
- cna_query_volume_perf (host);
- cna_query_volume_usage (host);
- cna_query_system (host);
+
+ status = cna_read_internal (host);
+ if (status != 0)
+ {
+ if (host->srv != NULL)
+ na_server_close (host->srv);
+ host->srv = NULL;
+ }
return 0;
} /* }}} int cna_read */