X-Git-Url: https://git.octo.it/?a=blobdiff_plain;ds=sidebyside;f=src%2Fnetapp.c;h=b11e9fa263281aff605b1881f7e1912f0f09e261;hb=0a73779531039d715e8ca405658c65ba03fad408;hp=f47b0366a13aecdba3d5d2495f58cc4fc2ac4cc1;hpb=21a2da50cf272a88769e5794f2e3b57ac9256a92;p=collectd.git diff --git a/src/netapp.c b/src/netapp.c index f47b0366..b11e9fa2 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -190,6 +190,7 @@ typedef struct { #define HAVE_VOLUME_USAGE_SNAP_USED 0x0080 #define HAVE_VOLUME_USAGE_SIS_SAVED 0x0100 #define HAVE_VOLUME_USAGE_ALL 0x01f0 +#define IS_VOLUME_USAGE_OFFLINE 0x0200 struct data_volume_usage_s; typedef struct data_volume_usage_s data_volume_usage_t; struct data_volume_usage_s { @@ -730,11 +731,19 @@ static int submit_volume_perf_data (const char *hostname, /* {{{ */ data_volume_perf_t *old_data, const data_volume_perf_t *new_data) { + char plugin_instance[DATA_MAX_NAME_LEN]; + + if ((hostname == NULL) || (old_data == NULL) || (new_data == NULL)) + return (-1); + + ssnprintf (plugin_instance, sizeof (plugin_instance), + "volume-%s", old_data->name); + /* Check for and submit disk-octet values */ 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, old_data->name, "disk_octets", /* type instance = */ NULL, + 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); } @@ -742,7 +751,7 @@ static int submit_volume_perf_data (const char *hostname, /* {{{ */ 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, old_data->name, "disk_ops", /* type instance = */ NULL, + 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); } @@ -786,7 +795,7 @@ static int submit_volume_perf_data (const char *hostname, /* {{{ */ latency_per_op_write = ((gauge_t) diff_latency_write) / ((gauge_t) diff_ops_write); } - submit_two_gauge (hostname, old_data->name, "disk_latency", /* type instance = */ NULL, + submit_two_gauge (hostname, plugin_instance, "disk_latency", /* type instance = */ NULL, latency_per_op_read, latency_per_op_write, new_data->timestamp); } @@ -1348,6 +1357,8 @@ static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */ for (v = cfg_volume->volumes; v != NULL; v = v->next) { + char plugin_instance[DATA_MAX_NAME_LEN]; + uint64_t norm_used = v->norm_used; uint64_t norm_free = v->norm_free; uint64_t sis_saved = v->sis_saved; @@ -1355,6 +1366,9 @@ static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */ uint64_t snap_reserve_free = v->snap_reserved; uint64_t snap_norm_used = v->snap_used; + ssnprintf (plugin_instance, sizeof (plugin_instance), + "volume-%s", v->name); + if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_USED | HAVE_VOLUME_USAGE_SNAP_RSVD)) { if (v->snap_reserved > v->snap_used) { snap_reserve_free = v->snap_reserved - v->snap_used; @@ -1364,39 +1378,51 @@ static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */ snap_reserve_free = 0; snap_reserve_used = v->snap_reserved; snap_norm_used = v->snap_used - v->snap_reserved; - if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_USED) - && (norm_used >= snap_norm_used)) - norm_used -= snap_norm_used; + } + } + + /* The space used by snapshots but not reserved for them is included in + * both, norm_used and snap_norm_used. If possible, subtract this here. */ + if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_USED | HAVE_VOLUME_USAGE_SNAP_USED)) + { + if (norm_used >= snap_norm_used) + norm_used -= snap_norm_used; + else + { + ERROR ("netapp plugin: (norm_used = %"PRIu64") < (snap_norm_used = " + "%"PRIu64"). Invalidating both.", + norm_used, snap_norm_used); + v->flags &= ~(HAVE_VOLUME_USAGE_NORM_USED | HAVE_VOLUME_USAGE_SNAP_USED); } } if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_FREE)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "free", (double) norm_free, /* timestamp = */ 0); if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SIS_SAVED)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "sis_saved", (double) sis_saved, /* timestamp = */ 0); if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_USED)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "used", (double) norm_used, /* timestamp = */ 0); if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_RSVD)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "snap_reserved", (double) snap_reserve_free, /* timestamp = */ 0); if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_USED | HAVE_VOLUME_USAGE_SNAP_RSVD)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "snap_reserve_used", (double) snap_reserve_used, /* timestamp = */ 0); if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_USED)) - submit_double (hostname, /* plugin instance = */ v->name, + submit_double (hostname, /* plugin instance = */ plugin_instance, "df_complex", "snap_normal_used", (double) snap_norm_used, /* timestamp = */ 0); @@ -1407,7 +1433,36 @@ static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */ return (0); } /* }}} int cna_submit_volume_usage_data */ -static void cna_handle_volume_snap_usage(const host_config_t *host, data_volume_usage_t *v) +/* Switch the state of a volume between online and offline and send out a + * notification. */ +static int cna_change_volume_status (const char *hostname, /* {{{ */ + data_volume_usage_t *v) +{ + notification_t n; + + memset (&n, 0, sizeof (&n)); + n.time = time (NULL); + sstrncpy (n.host, hostname, sizeof (n.host)); + sstrncpy (n.plugin, "netapp", sizeof (n.plugin)); + sstrncpy (n.plugin_instance, v->name, sizeof (n.plugin_instance)); + + if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0) { + n.severity = NOTIF_OKAY; + ssnprintf (n.message, sizeof (n.message), + "Volume %s is now online.", v->name); + v->flags &= ~IS_VOLUME_USAGE_OFFLINE; + } else { + n.severity = NOTIF_WARNING; + ssnprintf (n.message, sizeof (n.message), + "Volume %s is now offline.", v->name); + v->flags |= IS_VOLUME_USAGE_OFFLINE; + } + + return (plugin_dispatch_notification (&n)); +} /* }}} int cna_change_volume_status */ + +static void cna_handle_volume_snap_usage(const host_config_t *host, /* {{{ */ + data_volume_usage_t *v) { uint64_t snap_used = 0, value; na_elem_t *data, *elem_snap, *elem_snapshots; @@ -1416,14 +1471,21 @@ static void cna_handle_volume_snap_usage(const host_config_t *host, data_volume_ data = na_server_invoke_elem(host->srv, v->snap_query); if (na_results_status(data) != NA_OK) { - if (na_results_errno(data) != EVOLUMEOFFLINE) + if (na_results_errno(data) == EVOLUMEOFFLINE) { + if ((v->flags & IS_VOLUME_USAGE_OFFLINE) == 0) + cna_change_volume_status (host->name, v); + } else { ERROR ("netapp plugin: cna_handle_volume_snap_usage: na_server_invoke_elem for " "volume \"%s\" failed with error %d: %s", v->name, na_results_errno(data), na_results_reason(data)); + } na_elem_free(data); return; } + if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0) + cna_change_volume_status (host->name, v); + elem_snapshots = na_elem_child (data, "snapshots"); if (elem_snapshots == NULL) { @@ -1439,15 +1501,17 @@ static void cna_handle_volume_snap_usage(const host_config_t *host, data_volume_ elem_snap = na_iterator_next (&iter_snap)) { value = na_child_get_uint64(elem_snap, "cumulative-total", 0); + /* "cumulative-total" is the total size of the oldest snapshot plus all + * newer ones in blocks (1KB). We therefore are looking for the highest + * number of all snapshots - that's the size required for the snapshots. */ if (value > snap_used) snap_used = value; } na_elem_free (data); - /* snap_used is the total size of the oldest snapshot plus all - * newer ones in blocks (1KB). */ + /* snap_used is in 1024 byte blocks */ v->snap_used = snap_used * 1024; v->flags |= HAVE_VOLUME_USAGE_SNAP_USED; -} +} /* }}} void cna_handle_volume_snap_usage */ static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */ cfg_volume_usage_t *cfg_volume, na_elem_t *data)