From 194379810c9113c8eedd79c883ab6e960e5b4162 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Fri, 25 Jan 2013 14:17:46 +0100 Subject: [PATCH] =?utf8?q?netapp=20plugin:=20Added=20VFiler=C2=AE=20suppor?= =?utf8?q?t.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The plugin now accepts the config block (inside blocks). This is treated similar to blocks (it accepts all the same config options) and it inherits all connection related settings from the surrounding block (which may, however, be overwritten inside the block). However, all data collecting operations are done in the context of the specified VFiler®. --- src/collectd.conf.pod | 42 ++++++++- src/netapp.c | 200 +++++++++++++++++++++++++++++++++--------- 2 files changed, 200 insertions(+), 42 deletions(-) diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 080b253e..9fac6a6e 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -2527,6 +2527,13 @@ Required capabilities are documented below. GetDiskOps true GetDiskIO true + + + Interval 60 + + SnapVault true + # ... + @@ -2537,7 +2544,27 @@ The netapp plugin accepts the following configuration options: =item B I A host block defines one NetApp filer. It will appear in collectd with the name -you specify here which does not have to be its real name nor its hostname. +you specify here which does not have to be its real name nor its hostname (see +the B
option below). + +=item B I + +A B block may only be used inside a host block. It accepts all the +same options as the B block (except for cascaded B blocks) and +will execute all NetApp API commands in the context of the specified +VFiler(R). It will appear in collectd with the name you specify here which +does not have to be its real name. The VFiler name may be specified using the +B option. If this is not specified, it will default to the name +you specify here. + +The VFiler block inherits all connection related settings from the surrounding +B block (which appear before the B block) but they may be +overwritten inside the B block. + +This feature is useful, for example, when using a VFiler as SnapVault target +(supported since OnTap 8.1). In that case, the SnapVault statistics are not +available in the host filer (vfiler0) but only in the respective VFiler +context. =item B B|B @@ -2581,6 +2608,19 @@ Mandatory Type: string +=item B I + +The name of the VFiler in which context to execute API commands. If not +specified, the name provided to the B block will be used instead. + +Optional + +Type: string + +Default: name of the B block + +B This option may only be used inside B blocks. + =item B I B diff --git a/src/netapp.c b/src/netapp.c index f7197245..e65ec0e6 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -252,6 +252,7 @@ struct host_config_s { int port; char *username; char *password; + char *vfiler; cdtime_t interval; na_server_t *srv; @@ -400,6 +401,7 @@ static void free_host_config (host_config_t *hc) /* {{{ */ sfree (hc->host); sfree (hc->username); sfree (hc->password); + sfree (hc->vfiler); free_cfg_disk (hc->cfg_disk); free_cfg_wafl (hc->cfg_wafl); @@ -2585,25 +2587,21 @@ static int cna_config_system (host_config_t *host, /* {{{ */ } /* }}} int cna_config_system */ /* Corresponds to a block. */ -static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ +static host_config_t *cna_alloc_host (void) /* {{{ */ { - oconfig_item_t *item; host_config_t *host; - int status; - int i; - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("netapp plugin: \"Host\" needs exactly one string argument. Ignoring host block."); - return 0; - } host = malloc(sizeof(*host)); + if (! host) + return (NULL); memset (host, 0, sizeof (*host)); + host->name = NULL; host->protocol = NA_SERVER_TRANSPORT_HTTPS; host->host = NULL; host->username = NULL; host->password = NULL; + host->vfiler = NULL; host->srv = NULL; host->cfg_wafl = NULL; host->cfg_disk = NULL; @@ -2612,13 +2610,108 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ host->cfg_snapvault = NULL; host->cfg_system = NULL; - status = cf_util_get_string (ci, &host->name); - if (status != 0) - { - sfree (host); + return (host); +} /* }}} host_config_t *cna_alloc_host */ + +static host_config_t *cna_shallow_clone_host (host_config_t *host) /* {{{ */ +{ + host_config_t *clone; + + if (host == NULL) return (NULL); + + clone = cna_alloc_host (); + if (clone == NULL) + return (NULL); + + if (host->name != NULL) { + clone->name = strdup (host->name); + if (clone->name == NULL) { + free_host_config (clone); + return NULL; + } + } + + clone->protocol = host->protocol; + + if (host->host != NULL) { + clone->host = strdup (host->host); + if (clone->host == NULL) { + free_host_config (clone); + return NULL; + } + } + + clone->port = host->port; + + if (host->username != NULL) { + clone->username = strdup (host->username); + if (clone->username == NULL) { + free_host_config (clone); + return NULL; + } + } + if (host->password != NULL) { + clone->password = strdup (host->password); + if (clone->password == NULL) { + free_host_config (clone); + return NULL; + } + } + + clone->interval = host->interval; + + return (clone); +} /* }}} host_config_t *cna_shallow_clone_host */ + +static int cna_read (user_data_t *ud); + +static int cna_register_host (host_config_t *host) /* {{{ */ +{ + char cb_name[256]; + struct timespec interval; + user_data_t ud; + + if (host->vfiler) + ssnprintf (cb_name, sizeof (cb_name), "netapp-%s-%s", + host->name, host->vfiler); + else + ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name); + + CDTIME_T_TO_TIMESPEC (host->interval, &interval); + + memset (&ud, 0, sizeof (ud)); + ud.data = host; + ud.free_func = (void (*) (void *)) free_host_config; + + plugin_register_complex_read (/* group = */ NULL, cb_name, + /* callback = */ cna_read, + /* interval = */ (host->interval > 0) ? &interval : NULL, + /* user data = */ &ud); + + return (0); +} /* }}} int cna_register_host */ + +static int cna_config_host (host_config_t *host, /* {{{ */ + const oconfig_item_t *ci) +{ + oconfig_item_t *item; + _Bool is_vfiler = 0; + int status; + int i; + + if (! strcasecmp (ci->key, "VFiler")) + is_vfiler = 1; + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { + WARNING ("netapp plugin: \"%s\" needs exactly one string argument. Ignoring host block.", ci->key); + return (1); } + status = cf_util_get_string (ci, &host->name); + if (status != 0) + return (1); + for (i = 0; i < ci->children_num; ++i) { item = ci->children + i; @@ -2635,7 +2728,7 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ } else if (!strcasecmp(item->key, "Protocol")) { if ((item->values_num != 1) || (item->values[0].type != OCONFIG_TYPE_STRING) || (strcasecmp(item->values[0].value.string, "http") && strcasecmp(item->values[0].value.string, "https"))) { WARNING("netapp plugin: \"Protocol\" needs to be either \"http\" or \"https\". Ignoring host block \"%s\".", ci->values[0].value.string); - return 0; + return (1); } if (!strcasecmp(item->values[0].value.string, "http")) host->protocol = NA_SERVER_TRANSPORT_HTTP; else host->protocol = NA_SERVER_TRANSPORT_HTTPS; @@ -2657,9 +2750,26 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ cna_config_snapvault(host, item); } else if (!strcasecmp(item->key, "System")) { cna_config_system(host, item); + } else if ((!strcasecmp(item->key, "VFiler")) && (! is_vfiler)) { + host_config_t *vfiler; + + vfiler = cna_shallow_clone_host (host); + if (! vfiler) { + ERROR ("netapp plugin: Failed to allocate host object for vfiler."); + continue; + } + + if (cna_config_host (vfiler, item)) { + free_host_config (vfiler); + continue; + } + + cna_register_host (vfiler); + } else if ((!strcasecmp(item->key, "VFilerName")) && is_vfiler) { + status = cf_util_get_string (item, &host->vfiler); } else { - WARNING("netapp plugin: Ignoring unknown config option \"%s\" in host block \"%s\".", - item->key, ci->values[0].value.string); + WARNING ("netapp plugin: Ignoring unknown config option \"%s\" in %s block \"%s\".", + item->key, is_vfiler ? "vfiler" : "host", ci->values[0].value.string); } if (status != 0) @@ -2669,6 +2779,9 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ if (host->host == NULL) host->host = strdup (host->name); + if (is_vfiler && (! host->vfiler)) + host->vfiler = strdup (host->name); + if (host->host == NULL) status = -1; @@ -2682,12 +2795,9 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ } if (status != 0) - { - free_host_config (host); - return (NULL); - } + return status; - return host; + return (0); } /* }}} host_config_t *cna_config_host */ /* @@ -2697,15 +2807,19 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ */ static int cna_init_host (host_config_t *host) /* {{{ */ { + /* Request version 1.1 of the ONTAP API */ + int major_version = 1, minor_version = 1; + if (host == NULL) return (EINVAL); if (host->srv != NULL) return (0); - /* Request version 1.1 of the ONTAP API */ - host->srv = na_server_open(host->host, - /* major version = */ 1, /* minor version = */ 1); + if (host->vfiler != NULL) /* Request version 1.7 of the ONTAP API */ + minor_version = 7; + + host->srv = na_server_open (host->host, major_version, minor_version); if (host->srv == NULL) { ERROR ("netapp plugin: na_server_open (%s) failed.", host->host); return (-1); @@ -2718,6 +2832,18 @@ static int cna_init_host (host_config_t *host) /* {{{ */ na_server_adminuser(host->srv, host->username, host->password); na_server_set_timeout(host->srv, 5 /* seconds */); + if (host->vfiler != NULL) { + if (! na_server_set_vfiler (host->srv, host->vfiler)) { + ERROR ("netapp plugin: Failed to connect to VFiler '%s' on host '%s'.", + host->vfiler, host->host); + return (-1); + } + else { + INFO ("netapp plugin: Connected to VFiler '%s' on host '%s'.", + host->vfiler, host->host); + } + } + return (0); } /* }}} int cna_init_host */ @@ -2799,27 +2925,19 @@ static int cna_config (oconfig_item_t *ci) { /* {{{ */ if (strcasecmp(item->key, "Host") == 0) { host_config_t *host; - char cb_name[256]; - struct timespec interval; - user_data_t ud; - host = cna_config_host (item); - if (host == NULL) + host = cna_alloc_host (); + if (host == NULL) { + ERROR ("netapp plugin: Failed to allocate host object."); continue; + } - ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name); - - CDTIME_T_TO_TIMESPEC (host->interval, &interval); - - memset (&ud, 0, sizeof (ud)); - ud.data = host; - ud.free_func = (void (*) (void *)) free_host_config; + if (cna_config_host (host, item) != 0) { + free_host_config (host); + continue; + } - plugin_register_complex_read (/* group = */ NULL, cb_name, - /* callback = */ cna_read, - /* interval = */ (host->interval > 0) ? &interval : NULL, - /* user data = */ &ud); - continue; + cna_register_host (host); } else /* if (item->key != "Host") */ { -- 2.30.2