- na_elem_t *instances;
- 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;
- uint32_t counter_flags = 0;
-
- const char *instance;
- time_t timestamp;
-
- timestamp = (time_t) na_child_get_uint64 (data, "timestamp", 0);
-
- instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
- if (instances == NULL)
- {
- ERROR ("netapp plugin: cna_handle_system_data: "
- "na_elem_child (\"instances\") failed "
- "for host %s.", hostname);
- return (-1);
- }
-
- instance = na_child_get_string (instances, "name");
- if (instance == NULL)
- {
- ERROR ("netapp plugin: cna_handle_system_data: "
- "na_child_get_string (\"name\") failed "
- "for host %s.", hostname);
- return (-1);
- }
-
- counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
- for (counter = na_iterator_next (&counter_iter);
- counter != NULL;
- counter = na_iterator_next (&counter_iter))
- {
- const char *name;
- uint64_t value;
-
- name = na_child_get_string(counter, "name");
- if (name == NULL)
- continue;
-
- value = na_child_get_uint64(counter, "value", UINT64_MAX);
- if (value == UINT64_MAX)
- continue;
-
- if (!strcmp(name, "disk_data_read")) {
- disk_read = (counter_t) (value * 1024);
- counter_flags |= 0x01;
- } else if (!strcmp(name, "disk_data_written")) {
- disk_written = (counter_t) (value * 1024);
- counter_flags |= 0x02;
- } else if (!strcmp(name, "net_data_recv")) {
- net_recv = (counter_t) (value * 1024);
- counter_flags |= 0x04;
- } else if (!strcmp(name, "net_data_sent")) {
- net_sent = (counter_t) (value * 1024);
- counter_flags |= 0x08;
- } else if (!strcmp(name, "cpu_busy")) {
- cpu_busy = (counter_t) value;
- counter_flags |= 0x10;
- } else if (!strcmp(name, "cpu_elapsed_time")) {
- cpu_total = (counter_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);
- }
- } /* for (counter) */
-
- if ((cfg_system->flags & CFG_SYSTEM_DISK)
- && (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
- submit_two_counters (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,
- 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",
- cpu_busy, timestamp, interval);
- submit_counter (hostname, instance, "cpu", "idle",
- cpu_total - cpu_busy, timestamp, interval);
- }
-
- return (0);
+ 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) {
+ na_elem_t *status_list = na_elem_child(data, "status-list");
+ if (status_list == NULL) {
+ ERROR("netapp plugin: SnapVault status record missing status-list");
+ return (0);
+ }
+
+ na_elem_iter_t status_iter = na_child_iterator(status_list);
+ for (na_elem_t *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;
+
+ 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 (uint32_t 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->cfg_snapvault->interval.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 *instances;
+ na_elem_iter_t counter_iter;
+
+ 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;
+ cdtime_t timestamp;
+
+ timestamp = cna_child_get_cdtime(data);
+
+ instances = na_elem_child(na_elem_child(data, "instances"), "instance-data");
+ if (instances == NULL) {
+ ERROR("netapp plugin: cna_handle_system_data: "
+ "na_elem_child (\"instances\") failed "
+ "for host %s.",
+ hostname);
+ return (-1);
+ }
+
+ instance = na_child_get_string(instances, "name");
+ if (instance == NULL) {
+ ERROR("netapp plugin: cna_handle_system_data: "
+ "na_child_get_string (\"name\") failed "
+ "for host %s.",
+ hostname);
+ return (-1);
+ }
+
+ counter_iter = na_child_iterator(na_elem_child(instances, "counters"));
+ for (na_elem_t *counter = na_iterator_next(&counter_iter); counter != NULL;
+ counter = na_iterator_next(&counter_iter)) {
+ const char *name;
+ uint64_t value;
+
+ name = na_child_get_string(counter, "name");
+ if (name == NULL)
+ continue;
+
+ value = na_child_get_uint64(counter, "value", UINT64_MAX);
+ if (value == UINT64_MAX)
+ continue;
+
+ if (!strcmp(name, "disk_data_read")) {
+ disk_read = (derive_t)(value * 1024);
+ counter_flags |= 0x01;
+ } else if (!strcmp(name, "disk_data_written")) {
+ disk_written = (derive_t)(value * 1024);
+ counter_flags |= 0x02;
+ } else if (!strcmp(name, "net_data_recv")) {
+ net_recv = (derive_t)(value * 1024);
+ counter_flags |= 0x04;
+ } else if (!strcmp(name, "net_data_sent")) {
+ net_sent = (derive_t)(value * 1024);
+ counter_flags |= 0x08;
+ } else if (!strcmp(name, "cpu_busy")) {
+ cpu_busy = (derive_t)value;
+ counter_flags |= 0x10;
+ } else if (!strcmp(name, "cpu_elapsed_time")) {
+ 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_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_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_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_derive(hostname, instance, "cpu", "system", cpu_busy, timestamp,
+ interval);
+ submit_derive(hostname, instance, "cpu", "idle", cpu_total - cpu_busy,
+ timestamp, interval);
+ }
+
+ return (0);