void noit_lua_check_clean_events(noit_lua_check_info_t *ci) { if(ci->events == NULL) return; noit_hash_destroy(ci->events, NULL, noit_event_dispose); free(ci->events); ci->events = NULL; }
void noit_console_closure_free(void *vncct) { noit_console_closure_t ncct = (noit_console_closure_t) vncct; noit_log_stream_t lf; noitL(noit_debug, "ncct free(%p)\n", (void *)ncct); if(ncct->el) el_end(ncct->el); if(ncct->hist) { history_end(ncct->hist); noitL(noit_debug, "ncct free->hist(%p)\n", (void *)ncct->hist); free(ncct->hist); } if(ncct->pty_master >= 0) close(ncct->pty_master); if(ncct->pty_slave >= 0) close(ncct->pty_slave); if(ncct->outbuf) free(ncct->outbuf); if(ncct->telnet) noit_console_telnet_free(ncct->telnet); noit_hash_destroy(&ncct->userdata, NULL, noit_console_userdata_free); while(ncct->state_stack) { noit_console_state_stack_t *tmp; tmp = ncct->state_stack; ncct->state_stack = tmp->last; if(tmp->name) free(tmp->name); free(tmp); } lf = noit_log_stream_find(ncct->feed_path); noit_log_stream_remove(ncct->feed_path); if(lf) { noit_log_stream_free(lf); } free(ncct); }
void noit_poller_free_check(noit_check_t *checker) { noit_module_t *mod; if(checker->flags & NP_RUNNING) { recycle_check(checker); return; } mod = noit_module_lookup(checker->module); if(mod->cleanup) mod->cleanup(mod, checker); if(checker->fire_event) { eventer_remove(checker->fire_event); free(checker->fire_event->closure); eventer_free(checker->fire_event); checker->fire_event = NULL; } if(checker->closure) free(checker->closure); if(checker->target) free(checker->target); if(checker->module) free(checker->module); if(checker->name) free(checker->name); if(checker->config) { noit_hash_destroy(checker->config, free, free); free(checker->config); checker->config = NULL; } free(checker); }
static int stratcon_datastore_journal_sync(eventer_t e, int mask, void *closure, struct timeval *now) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *vij; interim_journal_t *ij; syncset_t *syncset = closure; if((mask & EVENTER_ASYNCH) == EVENTER_ASYNCH) { if(syncset->completion) { eventer_add(syncset->completion); eventer_trigger(syncset->completion, EVENTER_READ | EVENTER_WRITE); } free(syncset); return 0; } if(!((mask & EVENTER_ASYNCH_WORK) == EVENTER_ASYNCH_WORK)) return 0; noitL(ds_deb, "Syncing journal sets...\n"); if (syncset->ws) { while(noit_hash_next(syncset->ws, &iter, &k, &klen, &vij)) { char tmppath[PATH_MAX], id_str[32]; int suffix_idx; ij = vij; noitL(ds_deb, "Syncing journal set [%s,%s,%s]\n", ij->remote_str, ij->remote_cn, ij->fqdn); strlcpy(tmppath, ij->filename, sizeof(tmppath)); suffix_idx = strlen(ij->filename) - 4; /* . t m p */ ij->filename[suffix_idx] = '\0'; if(rename(tmppath, ij->filename) != 0) { if(errno == EEXIST) { unlink(ij->filename); if(rename(tmppath, ij->filename) != 0) goto rename_failed; } else { rename_failed: noitL(noit_error, "rename failed(%s): (%s->%s)\n", strerror(errno), tmppath, ij->filename); exit(-1); } } fsync(ij->fd); close(ij->fd); ij->fd = -1; snprintf(id_str, sizeof(id_str), "%d", ij->storagenode_id); stratcon_ingest(ij->filename, ij->remote_str, ij->remote_cn, id_str); } noit_hash_destroy(syncset->ws, free, interim_journal_free); free(syncset->ws); } else { noitL(noit_error, "attempted to sync non-existing working set\n"); } return 0; }
void noit_check_set_stats(struct _noit_module *module, noit_check_t *check, stats_t *newstate) { int report_change = 0; dep_list_t *dep; if(check->stats.previous.status) free(check->stats.previous.status); noit_hash_destroy(&check->stats.previous.metrics, NULL, __free_metric); memcpy(&check->stats.previous, &check->stats.current, sizeof(stats_t)); memcpy(&check->stats.current, newstate, sizeof(stats_t)); if(check->stats.current.status) check->stats.current.status = strdup(check->stats.current.status); /* check for state changes */ if(check->stats.current.available != NP_UNKNOWN && check->stats.previous.available != NP_UNKNOWN && check->stats.current.available != check->stats.previous.available) report_change = 1; if(check->stats.current.state != NP_UNKNOWN && check->stats.previous.state != NP_UNKNOWN && check->stats.current.state != check->stats.previous.state) report_change = 1; noitL(noit_debug, "%s`%s <- [%s]\n", check->target, check->name, check->stats.current.status); if(report_change) { noitL(noit_debug, "%s`%s -> [%s:%s]\n", check->target, check->name, noit_check_available_string(check->stats.current.available), noit_check_state_string(check->stats.current.state)); } /* Write out our status */ noit_check_log_status(check); /* Write out all metrics */ noit_check_log_metrics(check); /* count the check as complete */ check_completion_count++; for(dep = check->causal_checks; dep; dep = dep->next) { noit_module_t *mod; mod = noit_module_lookup(dep->check->module); assert(mod); noitL(noit_debug, "Firing %s`%s in response to %s`%s\n", dep->check->target, dep->check->name, check->target, check->name); if((dep->check->flags & NP_DISABLED) == 0) if(mod->initiate_check) mod->initiate_check(mod, dep->check, 1, check); } }
static int noit_lua_module_config(noit_module_t *mod, noit_hash_table *options) { LMC_DECL(L, mod); SETUP_CALL(L, "config", return 0); noit_lua_setup_module(L, mod); noit_lua_hash_to_table(L, options); noit_hash_destroy(options, free, free); free(options); lua_pcall(L, 2, 1, 0); /* If rv == 0, the caller will free options. We've * already freed options, that would be bad. fudge -> 1 */ RETURN_INT(L, "config", { rv = (rv == 0) ? 1 : rv; });
static int noit_statsd_config(noit_module_t *self, noit_hash_table *options) { statsd_mod_config_t *conf; conf = noit_module_get_userdata(self); if(conf) { if(conf->options) { noit_hash_destroy(conf->options, free, free); free(conf->options); } } else conf = calloc(1, sizeof(*conf)); conf->options = options; noit_module_set_userdata(self, conf); return 1; }
static int external_config(noit_module_t *self, noit_hash_table *options) { external_data_t *data; data = noit_module_get_userdata(self); if(data) { if(data->options) { noit_hash_destroy(data->options, free, free); free(data->options); } } else data = calloc(1, sizeof(*data)); data->options = options; if(!data->options) data->options = calloc(1, sizeof(*data->options)); noit_module_set_userdata(self, data); return 1; }
static int configure_eventer() { int rv = 0; noit_hash_table *table; table = noit_conf_get_hash(NULL, "/" APPNAME "/eventer/config"); if(table) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key, *value; int klen; while(noit_hash_next_str(table, &iter, &key, &klen, &value)) { int subrv; if((subrv = eventer_propset(key, value)) != 0) rv = subrv; } noit_hash_destroy(table, free, free); free(table); } return rv; }
void noit_log_stream_free(noit_log_stream_t ls) { if(ls) { struct _noit_log_stream_outlet_list *node; if(ls->name) free(ls->name); if(ls->path) free(ls->path); while(ls->outlets) { node = ls->outlets->next; free(ls->outlets); ls->outlets = node; } if(ls->config) { noit_hash_destroy(ls->config, free, free); free(ls->config); } if(ls->lock) { pthread_rwlock_destroy(ls->lock); free(ls->lock); } free(ls); } }
static int configure_eventer(const char *appname) { int rv = 0; noit_hash_table *table; char appscratch[1024]; snprintf(appscratch, sizeof(appscratch), "/%s/eventer/config", appname); table = noit_conf_get_hash(NULL, appscratch); if(table) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key, *value; int klen; while(noit_hash_next_str(table, &iter, &key, &klen, &value)) { int subrv; if((subrv = eventer_propset(key, value)) != 0) rv = subrv; } noit_hash_destroy(table, free, free); free(table); } return rv; }
int stratcon_line_to_javascript(noit_http_session_ctx *ctx, char *buff, u_int32_t inc_id) { char buffer[1024]; char *scp, *ecp, *token; int len; void *vcb; const char *v, *cb = NULL; noit_hash_table json = NOIT_HASH_EMPTY; char s_inc_id[42]; snprintf(s_inc_id, sizeof(s_inc_id), "script-%08x", inc_id); if(noit_hash_retrieve(&ctx->req.querystring, "cb", strlen("cb"), &vcb)) cb = vcb; for(v = cb; v && *v; v++) if(!((*v >= '0' && *v <= '9') || (*v >= 'a' && *v <= 'z') || (*v >= 'A' && *v <= 'Z') || (*v == '_') || (*v == '.'))) { cb = NULL; break; } if(!cb) cb = "window.parent.plot_iframe_data"; #define BAIL_HTTP_WRITE do { \ noit_hash_destroy(&json, NULL, free); \ noitL(noit_error, "javascript emit failed: %s:%s:%d\n", \ __FILE__, __FUNCTION__, __LINE__); \ return -1; \ } while(0) #define PROCESS_NEXT_FIELD(t,l) do { \ if(!*scp) goto bad_row; \ ecp = strchr(scp, '\t'); \ if(!ecp) goto bad_row; \ t = scp; \ l = (ecp-scp); \ scp = ecp + 1; \ } while(0) #define PROCESS_LAST_FIELD(t,l) do { \ if(!*scp) ecp = scp; \ else { \ ecp = scp + strlen(scp); /* Puts us at the '\0' */ \ if(*(ecp-1) == '\n') ecp--; /* We back up on letter if we ended in \n */ \ } \ t = scp; \ l = (ecp-scp); \ } while(0) scp = buff; PROCESS_NEXT_FIELD(token,len); /* Skip the leader */ if(buff[0] == 'M') { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key; int klen, i=0; void *vval; #define ra_write(a,b) if(noit_http_response_append(ctx, a, b) == noit_false) BAIL_HTTP_WRITE snprintf(buffer, sizeof(buffer), "<script id=\"%s\">%s({", s_inc_id, cb); ra_write(buffer, strlen(buffer)); while(noit_hash_next(&ctx->req.querystring, &iter, &key, &klen, &vval)) { if(!strcmp(key, "cb")) continue; noit_hash_store(&json, key, klen, strdup(vval ?(char *)vval : "true")); } /* Time */ noit_hash_store(&json, "script_id", 9, strdup(s_inc_id)); noit_hash_store(&json, "type", 4, strdup("M")); PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "time", 4, noit__strndup(token, len)); /* UUID */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "id", 2, noit__strndup(token, len)); /* name */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_name", 11, noit__strndup(token, len)); /* type */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_type", 11, noit__strndup(token, len)); /* value */ PROCESS_LAST_FIELD(token,len); /* value */ noit_hash_store(&json, "value", 5, noit__strndup(token, len)); memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&json, &iter, &key, &klen, &vval)) { char *val = (char *)vval; if(i++) ra_write(",", 1); ra_write("'", 1); ra_write(key, klen); ra_write("':\"", 3); while(*val) { if(*val == '\"' || *val == '\\') { ra_write((char *)"\\", 1); } if(isprint(*val)) { ra_write((char *)val, 1); } else { char od[5]; snprintf(od, sizeof(od), "\\%03o", *((unsigned char *)val)); ra_write(od, strlen(od)); } val++; } ra_write("\"", 1); } snprintf(buffer, sizeof(buffer), "});</script>\n"); ra_write(buffer, strlen(buffer)); if(noit_http_response_flush(ctx, noit_false) == noit_false) BAIL_HTTP_WRITE; } noit_hash_destroy(&json, NULL, free); return 0; bad_row: BAIL_HTTP_WRITE; }
static int external_invoke(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { struct timeval when, p_int; external_closure_t *ecl; struct check_info *ci = (struct check_info *)check->closure; eventer_t newe; external_data_t *data; noit_hash_table check_attrs_hash = NOIT_HASH_EMPTY; int i, klen; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *name, *value; char interp_fmt[4096], interp_buff[4096]; data = noit_module_get_userdata(self); check->flags |= NP_RUNNING; noitL(data->nldeb, "external_invoke(%p,%s)\n", self, check->target); /* remove a timeout if we still have one -- we should unless someone * has set a lower timeout than the period. */ if(ci->timeout_event) { eventer_remove(ci->timeout_event); free(ci->timeout_event->closure); eventer_free(ci->timeout_event); ci->timeout_event = NULL; } check_info_clean(ci); gettimeofday(&when, NULL); memcpy(&check->last_fire_time, &when, sizeof(when)); /* Setup all our check bits */ ci->check_no = noit_atomic_inc64(&data->check_no_seq); ci->check = check; /* We might want to extract metrics */ if(noit_hash_retr_str(check->config, "output_extract", strlen("output_extract"), &value) != 0) { const char *error; int erroffset; ci->matcher = pcre_compile(value, 0, &error, &erroffset, NULL); if(!ci->matcher) { noitL(data->nlerr, "external pcre /%s/ failed @ %d: %s\n", value, erroffset, error); } } noit_check_make_attrs(check, &check_attrs_hash); /* Count the args */ i = 1; while(1) { char argname[10]; snprintf(argname, sizeof(argname), "arg%d", i); if(noit_hash_retr_str(check->config, argname, strlen(argname), &value) == 0) break; i++; } ci->argcnt = i + 1; /* path, arg0, (i-1 more args) */ ci->arglens = calloc(ci->argcnt, sizeof(*ci->arglens)); ci->args = calloc(ci->argcnt, sizeof(*ci->args)); /* Make the command */ if(noit_hash_retr_str(check->config, "command", strlen("command"), &value) == 0) { value = "/bin/true"; } ci->args[0] = strdup(value); ci->arglens[0] = strlen(ci->args[0]) + 1; i = 0; while(1) { char argname[10]; snprintf(argname, sizeof(argname), "arg%d", i); if(noit_hash_retr_str(check->config, argname, strlen(argname), &value) == 0) { if(i == 0) { /* if we don't have arg0, make it last element of path */ char *cp = ci->args[0] + strlen(ci->args[0]); while(cp > ci->args[0] && *(cp-1) != '/') cp--; value = cp; } else break; /* if we don't have argn, we're done */ } noit_check_interpolate(interp_buff, sizeof(interp_buff), value, &check_attrs_hash, check->config); ci->args[i+1] = strdup(interp_buff); ci->arglens[i+1] = strlen(ci->args[i+1]) + 1; i++; } /* Make the environment */ memset(&iter, 0, sizeof(iter)); ci->envcnt = 0; while(noit_hash_next_str(check->config, &iter, &name, &klen, &value)) if(!strncasecmp(name, "env_", 4)) ci->envcnt++; memset(&iter, 0, sizeof(iter)); ci->envlens = calloc(ci->envcnt, sizeof(*ci->envlens)); ci->envs = calloc(ci->envcnt, sizeof(*ci->envs)); ci->envcnt = 0; while(noit_hash_next_str(check->config, &iter, &name, &klen, &value)) if(!strncasecmp(name, "env_", 4)) { snprintf(interp_fmt, sizeof(interp_fmt), "%s=%s", name+4, value); noit_check_interpolate(interp_buff, sizeof(interp_buff), interp_fmt, &check_attrs_hash, check->config); ci->envs[ci->envcnt] = strdup(interp_buff); ci->envlens[ci->envcnt] = strlen(ci->envs[ci->envcnt]) + 1; ci->envcnt++; } noit_hash_destroy(&check_attrs_hash, NULL, NULL); noit_hash_store(&data->external_checks, (const char *)&ci->check_no, sizeof(ci->check_no), ci); /* Setup a timeout */ newe = eventer_alloc(); newe->mask = EVENTER_TIMER; gettimeofday(&when, NULL); p_int.tv_sec = check->timeout / 1000; p_int.tv_usec = (check->timeout % 1000) * 1000; add_timeval(when, p_int, &newe->whence); ecl = calloc(1, sizeof(*ecl)); ecl->self = self; ecl->check = check; newe->closure = ecl; newe->callback = external_timeout; eventer_add(newe); ci->timeout_event = newe; /* Setup push */ newe = eventer_alloc(); newe->mask = EVENTER_ASYNCH; add_timeval(when, p_int, &newe->whence); ecl = calloc(1, sizeof(*ecl)); ecl->self = self; ecl->check = check; newe->closure = ecl; newe->callback = external_enqueue; eventer_add(newe); return 0; }
void noit_listener_reconfig(const char *toplevel) { int i, cnt = 0; noit_conf_section_t *listener_configs; char path[256]; snprintf(path, sizeof(path), "/%s/listeners//listener", toplevel ? toplevel : "*"); listener_configs = noit_conf_get_sections(NULL, path, &cnt); noitL(noit_debug, "Found %d %s stanzas\n", cnt, path); for(i=0; i<cnt; i++) { char address[256]; char type[256]; unsigned short port; int portint; int backlog; eventer_func_t f; noit_boolean ssl; noit_hash_table *sslconfig, *config; if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@type", type, sizeof(type))) { noitL(noit_error, "No type specified in listener stanza %d\n", i+1); continue; } f = eventer_callback_for_name(type); if(!f) { noitL(noit_error, "Cannot find handler for listener type: '%s'\n", type); continue; } if(!noit_conf_get_stringbuf(listener_configs[i], "ancestor-or-self::node()/@address", address, sizeof(address))) { address[0] = '*'; address[1] = '\0'; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@port", &portint)) portint = 0; port = (unsigned short) portint; if(address[0] != '/' && (portint == 0 || (port != portint))) { /* UNIX sockets don't require a port (they'll ignore it if specified */ noitL(noit_error, "Invalid port [%d] specified in stanza %d\n", port, i+1); continue; } if(noit_listener_should_skip(address, port)) { if(port) noitL(noit_error, "Operator forced skipping listener %s:%d\n", address, port); else noitL(noit_error, "Operator forced skipping listener %s\n", address); continue; } if(!noit_conf_get_int(listener_configs[i], "ancestor-or-self::node()/@backlog", &backlog)) backlog = 5; if(!noit_conf_get_boolean(listener_configs[i], "ancestor-or-self::node()/@ssl", &ssl)) ssl = noit_false; sslconfig = ssl ? noit_conf_get_hash(listener_configs[i], "sslconfig") : NULL; config = noit_conf_get_hash(listener_configs[i], "config"); if(noit_listener(address, port, SOCK_STREAM, backlog, sslconfig, config, f, NULL) != 0) { noit_hash_destroy(config,free,free); free(config); } if(sslconfig) { /* A copy of this is made within noit_listener */ noit_hash_destroy(sslconfig,free,free); free(sslconfig); } } free(listener_configs); }
noit_check_t * noit_fire_check(xmlNodePtr attr, xmlNodePtr config, const char **error) { char *target = NULL, *name = NULL, *module = NULL, *filterset = NULL; int timeout = 0; noit_module_t *m; noit_check_t *c = NULL; xmlNodePtr a, co; noit_hash_table *conf_hash = NULL; for(a = attr->children; a; a = a->next) { if(!strcmp((char *)a->name, "target")) target = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "name")) name = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "module")) module = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "filterset")) filterset = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "timeout")) { char *timeout_str = (char *)xmlNodeGetContent(a); timeout = atoi(timeout_str); free(timeout_str); } } m = noit_module_lookup(module); if(!m) { *error = "cannot find requested module"; goto error; } conf_hash = calloc(1, sizeof(*conf_hash)); for(co = config->children; co; co = co->next) { char *name, *val; xmlChar *tmp_val; name = strdup((char *)co->name); tmp_val = xmlNodeGetContent(co); val = strdup(tmp_val ? (char *)tmp_val : ""); noit_hash_replace(conf_hash, name, strlen(name), val, free, free); xmlFree(tmp_val); } if(!m->initiate_check) { *error = "that module cannot run checks"; goto error; } c = calloc(1, sizeof(*c)); noit_check_update(c, target, name, filterset, conf_hash, 0, timeout, NULL, NP_TRANSIENT); c->module = strdup(module); uuid_generate(c->checkid); c->flags |= NP_DISABLED; /* this is hack to know we haven't run it yet */ if(NOIT_CHECK_SHOULD_RESOLVE(c)) noit_check_resolve(c); error: if(conf_hash) { noit_hash_destroy(conf_hash, free, free); free(conf_hash); } if(target) xmlFree(target); if(name) xmlFree(name); if(module) xmlFree(module); if(filterset) xmlFree(filterset); return c; }
static int noit_console_config_show(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; int i, cnt, titled = 0, cliplen = 0; const char *path = "", *basepath = NULL; char xpath[1024]; noit_conf_t_userdata_t *info = NULL; noit_hash_table *config; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; xmlDocPtr master_config = NULL; xmlNodePtr node = NULL; noit_conf_xml_xpath(&master_config, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "too many arguments\n"); return -1; } info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); if(info && info->path) path = basepath = info->path; if(!info && argc == 0) { nc_printf(ncct, "argument required when not in configuration mode\n"); return -1; } if(argc == 1) path = argv[0]; if(!basepath) basepath = path; /* { / } is a special case */ if(!strcmp(basepath, "/")) basepath = ""; if(!strcmp(path, "/")) path = ""; if(!master_config) { nc_printf(ncct, "no config\n"); return -1; } /* { / } is the only path that will end with a / * in XPath { / / * } means something _entirely different than { / * } * Ever notice how it is hard to describe xpath in C comments? */ /* We don't want to show the root node */ cliplen = strlen("/noit/"); /* If we are in configuration mode * and we are without an argument or the argument is absolute, * clip the current path off */ if(info && (argc == 0 || path[0] != '/')) cliplen += strlen(basepath); if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s/@*", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s/@*", basepath, path); current_ctxt = xpath_ctxt; pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children)) { if(!titled++) nc_printf(ncct, "== Section Settings ==\n"); nc_printf(ncct, "%s: %s\n", xmlGetNodePath(node) + cliplen, xmlXPathCastNodeToString(node->children)); } } xmlXPathFreeObject(pobj); /* Print out all the config settings */ if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s", basepath, path); pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt > 0) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); titled = 0; config = noit_conf_get_hash(node, "config"); while(noit_hash_next(config, &iter, &k, &klen, &data)) { if(!titled++) nc_printf(ncct, "== Section [Aggregated] Config ==\n"); nc_printf(ncct, "config::%s: %s\n", k, (const char *)data); } noit_hash_destroy(config, free, free); free(config); } xmlXPathFreeObject(pobj); /* _shorten string_ turning last { / @ * } to { / * } */ if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s/*", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s/*", basepath, path); pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(!strcmp((char *)node->name, "filterset")) continue; if(!strcmp((char *)xmlGetNodePath(node) + cliplen, "config")) continue; if(!(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children))) { if(!titled++) nc_printf(ncct, "== Subsections ==\n"); nc_printf(ncct, "%s\n", xmlGetNodePath(node) + cliplen); } } titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "filterset")) { xmlAttr *attr; char *filter_name = NULL; for(attr=node->properties; attr; attr = attr->next) { if(!strcmp((char *)attr->name, "name")) filter_name = (char *)xmlXPathCastNodeToString(attr->children); } if(filter_name) { nc_printf(ncct, "filterset[@name=\"%s\"]\n", filter_name); xmlFree(filter_name); } else nc_printf(ncct, "fitlerset\n"); } else if(!strcmp((char *)node->name, "check")) { int busted = 1; xmlAttr *attr; char *uuid_str = "undefined"; if(!titled++) nc_printf(ncct, "== Checks ==\n"); for(attr=node->properties; attr; attr = attr->next) { if(!strcmp((char *)attr->name, "uuid")) uuid_str = (char *)xmlXPathCastNodeToString(attr->children); } if(uuid_str) { uuid_t checkid; nc_printf(ncct, "check[@uuid=\"%s\"] ", uuid_str); if(uuid_parse(uuid_str, checkid) == 0) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check) { busted = 0; nc_printf(ncct, "%s`%s`%s", check->target, check->module, check->name); } } } else nc_printf(ncct, "%s ", xmlGetNodePath(node) + cliplen); if(busted) nc_printf(ncct, "[check not in running system]"); nc_write(ncct, "\n", 1); } } xmlXPathFreeObject(pobj); return 0; bad: if(pobj) xmlXPathFreeObject(pobj); return -1; }
static int noit_console_show_check(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { int i, cnt; noit_conf_t_userdata_t *info; char xpath[1024]; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; noit_conf_xml_xpath(NULL, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "requires zero or one arguments\n"); return -1; } info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); /* We many not be in conf-t mode -- that's fine */ if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, argc ? argv[0] : NULL)) { nc_printf(ncct, "could not find check '%s'\n", argv[0]); return -1; } pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { nc_printf(ncct, "no checks found\n"); goto out; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(info && cnt != 1) { nc_printf(ncct, "Ambiguous check specified\n"); goto out; } for(i=0; i<cnt; i++) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; uuid_t checkid; noit_check_t *check; noit_hash_table *config; xmlNodePtr node, anode, mnode = NULL; char *uuid_conf; char *module, *value; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { nc_printf(ncct, "%s has invalid or missing UUID!\n", (char *)xmlGetNodePath(node) + strlen("/noit")); continue; } nc_printf(ncct, "==== %s ====\n", uuid_conf); #define MYATTR(a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(a,n,b) \ _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(a) do { \ anode = NULL; \ value = NULL; \ INHERIT(a, anode, value); \ nc_attr_show(ncct, #a, node, anode, value); \ } while(0) if(!INHERIT(module, mnode, module)) module = NULL; if(MYATTR(name, anode, value)) nc_printf(ncct, " name: %s\n", value); else nc_printf(ncct, " name: %s [from module]\n", module ? module : "[undef]"); nc_attr_show(ncct, "module", node, mnode, module); SHOW_ATTR(target); SHOW_ATTR(period); SHOW_ATTR(timeout); SHOW_ATTR(oncheck); SHOW_ATTR(filterset); SHOW_ATTR(disable); /* Print out all the config settings */ config = noit_conf_get_hash(node, "config"); while(noit_hash_next(config, &iter, &k, &klen, &data)) { nc_printf(ncct, " config::%s: %s\n", k, (const char *)data); } noit_hash_destroy(config, free, free); free(config); check = noit_poller_lookup(checkid); if(!check) { nc_printf(ncct, " ERROR: not in running system\n"); } else { int idx = 0; nc_printf(ncct, " currently: "); if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":""); if(NOIT_CHECK_KILLED(check)) nc_printf(ncct, "%skilled", idx++?",":""); if(!NOIT_CHECK_CONFIGURED(check)) nc_printf(ncct, "%sunconfig", idx++?",":""); if(NOIT_CHECK_DISABLED(check)) nc_printf(ncct, "%sdisabled", idx++?",":""); if(!idx) nc_printf(ncct, "idle"); nc_write(ncct, "\n", 1); if(check->stats.current.whence.tv_sec == 0) { nc_printf(ncct, " last run: never\n"); } else { stats_t *c = &check->stats.current; struct timeval now, diff; gettimeofday(&now, NULL); sub_timeval(now, c->whence, &diff); nc_printf(ncct, " last run: %0.3f seconds ago\n", diff.tv_sec + (diff.tv_usec / 1000000.0)); nc_printf(ncct, " availability/state: %s/%s\n", noit_check_available_string(c->available), noit_check_state_string(c->state)); nc_printf(ncct, " status: %s\n", c->status ? c->status : "[[null]]"); nc_printf(ncct, " metrics:\n"); memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) { char buff[256]; noit_boolean filtered; noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data); filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data); nc_printf(ncct, " %c%s\n", filtered ? '*' : ' ', buff); } } } } out: if(pobj) xmlXPathFreeObject(pobj); return 0; }
int stratcon_line_to_javascript(noit_http_session_ctx *ctx, char *in_buff, u_int32_t *inc_id) { char buffer[1024]; char *scp, *ecp, *token, *buff; int i, len, cnt; const char *v, *cb = NULL; noit_hash_table json = NOIT_HASH_EMPTY; noit_http_request *req = noit_http_session_request(ctx); char s_inc_id[42]; char **outrows = NULL; cb = noit_http_request_querystring(req, "cb"); for(v = cb; v && *v; v++) if(!((*v >= '0' && *v <= '9') || (*v >= 'a' && *v <= 'z') || (*v >= 'A' && *v <= 'Z') || (*v == '_') || (*v == '.'))) { cb = NULL; break; } if(!cb) cb = "window.parent.plot_iframe_data"; #define BAIL_HTTP_WRITE do { \ if(outrows) { \ for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]); \ free(outrows); \ } \ noit_hash_destroy(&json, NULL, free); \ noitL(noit_error, "javascript emit failed: %s:%s:%d\n", \ __FILE__, __FUNCTION__, __LINE__); \ return -1; \ } while(0) #define PROCESS_NEXT_FIELD(t,l) do { \ if(!*scp) goto bad_row; \ ecp = strchr(scp, '\t'); \ if(!ecp) goto bad_row; \ t = scp; \ l = (ecp-scp); \ scp = ecp + 1; \ } while(0) #define PROCESS_LAST_FIELD(t,l) do { \ if(!*scp) ecp = scp; \ else { \ ecp = scp + strlen(scp); /* Puts us at the '\0' */ \ if(*(ecp-1) == '\n') ecp--; /* We back up on letter if we ended in \n */ \ } \ t = scp; \ l = (ecp-scp); \ } while(0) noitL(noit_error, "recv(%s)\n", in_buff); if(in_buff[0] == 'B' && in_buff[1] != '\0' && in_buff[2] == '\t') { cnt = noit_check_log_b_to_sm(in_buff, strlen(in_buff), &outrows); } else { cnt = 1; outrows = malloc(sizeof(*outrows)); outrows[0] = strdup(in_buff); } for(i=0; i<cnt; i++) { buff = outrows[i]; if(!buff) continue; noitL(noit_error, "recv_xlt(%s)\n", buff); scp = buff; PROCESS_NEXT_FIELD(token,len); /* Skip the leader */ if(buff[1] == '\t' && (buff[0] == 'M' || buff[0] == 'S')) { char target[256], module[256], name[256], uuid_str[UUID_STR_LEN+1]; noit_http_request *req = noit_http_session_request(ctx); noit_hash_table *qs; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key; int klen, i=0; void *vval; char type[2] = { '\0', '\0' }; type[0] = buff[0]; #define ra_write(a,b) if(noit_http_response_append(ctx, a, b) == noit_false) BAIL_HTTP_WRITE snprintf(s_inc_id, sizeof(s_inc_id), "script-%08x", (*inc_id)++); snprintf(buffer, sizeof(buffer), "<script id=\"%s\">%s({", s_inc_id, cb); ra_write(buffer, strlen(buffer)); qs = noit_http_request_querystring_table(req); while(noit_hash_next(qs, &iter, &key, &klen, &vval)) { if(!strcmp(key, "cb")) continue; noit_hash_store(&json, key, klen, strdup(vval ?(char *)vval : "true")); } /* Time */ noit_hash_store(&json, "script_id", 9, strdup(s_inc_id)); noit_hash_store(&json, "type", 4, strdup(type)); PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "time", 4, noit__strndup(token, len)); /* UUID */ PROCESS_NEXT_FIELD(token,len); noit_check_extended_id_split(token, len, target, sizeof(target), module, sizeof(module), name, sizeof(name), uuid_str, sizeof(uuid_str)); if(*uuid_str) noit_hash_store(&json, "id", 2, noit__strndup(uuid_str, strlen(uuid_str))); if(*target) noit_hash_store(&json, "check_target", 12, noit__strndup(target, strlen(target))); if(*module) noit_hash_store(&json, "check_module", 12, noit__strndup(module, strlen(module))); if(*name) noit_hash_store(&json, "check_name", 10, noit__strndup(name, strlen(name))); if(buff[0] == 'M') { /* name */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_name", 11, noit__strndup(token, len)); /* type */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_type", 11, noit__strndup(token, len)); /* value */ PROCESS_LAST_FIELD(token,len); /* value */ noit_hash_store(&json, "value", 5, noit__strndup(token, len)); } else if(buff[0] == 'S') { /* state */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_state", 11, noit__strndup(token, len)); /* availability */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_availability", 18, noit__strndup(token, len)); /* duration */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_duration_ms", 17, noit__strndup(token, len)); /* status */ PROCESS_LAST_FIELD(token,len); noit_hash_store(&json, "status_message", 14, noit__strndup(token, len)); } memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&json, &iter, &key, &klen, &vval)) { char *val = (char *)vval; if(i++) ra_write(",", 1); ra_write("\"", 1); ra_write(key, klen); ra_write("\":\"", 3); while(*val) { if(*val == '\"' || *val == '\\') { ra_write((char *)"\\", 1); } if(isprint(*val)) { ra_write((char *)val, 1); } else { char od[5]; snprintf(od, sizeof(od), "\\%03o", *((unsigned char *)val)); ra_write(od, strlen(od)); } val++; } ra_write("\"", 1); } snprintf(buffer, sizeof(buffer), "});</script>\n"); ra_write(buffer, strlen(buffer)); if(noit_http_response_flush(ctx, noit_false) == noit_false) BAIL_HTTP_WRITE; } noit_hash_destroy(&json, NULL, free); memset(&json, 0, sizeof(json)); } if(outrows) { for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]); free(outrows); } return 0; bad_row: BAIL_HTTP_WRITE; }
void noit_check_release_attrs(noit_hash_table *attrs) { noit_hash_destroy(attrs, NULL, NULL); }
static int dns_check_send(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { void *vnv_pair = NULL; struct dns_nameval *nv_pair; eventer_t newe; struct timeval p_int, now; struct dns_check_info *ci = check->closure; const char *config_val; const char *rtype = NULL; const char *nameserver = NULL; int port = 0; const char *port_str = NULL; const char *want_sort = NULL; const char *ctype = "IN"; const char *query = NULL; char interpolated_nameserver[1024]; char interpolated_query[1024]; noit_hash_table check_attrs_hash = NOIT_HASH_EMPTY; BAIL_ON_RUNNING_CHECK(check); gettimeofday(&now, NULL); memcpy(&check->last_fire_time, &now, sizeof(now)); ci->current.state = NP_BAD; ci->current.available = NP_UNAVAILABLE; ci->timed_out = 1; ci->nrr = 0; ci->sort = 1; if(!strcmp(check->name, "in-addr.arpa") || (strlen(check->name) >= sizeof("::in-addr.arpa") - 1 && !strcmp(check->name + strlen(check->name) - sizeof("::in-addr.arpa") + 1, "::in-addr.arpa"))) { /* in-addr.arpa defaults: * nameserver to NULL * rtype to PTR * query to %[:inaddrarpa:target] */ nameserver = NULL; rtype = "PTR"; query = "%[:inaddrarpa:target_ip]"; } else { nameserver = "%[target_ip]"; rtype = "A"; query = "%[name]"; } if(noit_hash_retr_str(check->config, "port", strlen("port"), &port_str)) { port = atoi(port_str); } #define CONFIG_OVERRIDE(a) \ if(noit_hash_retr_str(check->config, #a, strlen(#a), \ &config_val) && \ strlen(config_val) > 0) \ a = config_val CONFIG_OVERRIDE(ctype); CONFIG_OVERRIDE(nameserver); CONFIG_OVERRIDE(rtype); CONFIG_OVERRIDE(query); CONFIG_OVERRIDE(want_sort); if(nameserver && !strcmp(nameserver, "default")) nameserver = NULL; if(want_sort && strcasecmp(want_sort, "on") && strcasecmp(want_sort, "true")) ci->sort = 0; noit_check_make_attrs(check, &check_attrs_hash); if(nameserver) { noit_check_interpolate(interpolated_nameserver, sizeof(interpolated_nameserver), nameserver, &check_attrs_hash, check->config); nameserver = interpolated_nameserver; } if(query) { noit_check_interpolate(interpolated_query, sizeof(interpolated_query), query, &check_attrs_hash, check->config); query = interpolated_query; } noit_hash_destroy(&check_attrs_hash, NULL, NULL); check->flags |= NP_RUNNING; noitL(nldeb, "dns_check_send(%p,%s,%s,%s,%s,%s)\n", self, check->target, nameserver ? nameserver : "default", query ? query : "null", ctype, rtype); __activate_ci(ci); /* If this ci has a handle and it isn't the one we need, * we should release it */ if(ci->h && ((ci->h->ns == NULL && nameserver != NULL) || (ci->h->ns != NULL && nameserver == NULL) || (ci->h->ns && strcmp(ci->h->ns, nameserver)))) { dns_ctx_release(ci->h); ci->h = NULL; } /* use the cached one, unless we don't have one */ if(!ci->h) ci->h = dns_ctx_alloc(nameserver, port); if(!ci->h) ci->error = strdup("bad nameserver"); /* Lookup out class */ if(!noit_hash_retrieve(&dns_ctypes, ctype, strlen(ctype), &vnv_pair)) { if(ci->error) free(ci->error); ci->error = strdup("bad class"); } else { nv_pair = (struct dns_nameval *)vnv_pair; ci->query_ctype = nv_pair->val; } /* Lookup out rr type */ if(!noit_hash_retrieve(&dns_rtypes, rtype, strlen(rtype), &vnv_pair)) { if(ci->error) free(ci->error); ci->error = strdup("bad rr type"); } else { nv_pair = (struct dns_nameval *)vnv_pair; ci->query_rtype = nv_pair->val; } if(!ci->error) { /* Submit the query */ int abs; if(!dns_ptodn(query, strlen(query), ci->dn, sizeof(ci->dn), &abs) || !dns_submit_dn(ci->h->ctx, ci->dn, ci->query_ctype, ci->query_rtype, abs | DNS_NOSRCH, NULL, dns_cb, ci)) { ci->error = strdup("submission error"); } else { dns_timeouts(ci->h->ctx, -1, now.tv_sec); } } /* we could have completed by now... if so, we've nothing to do */ if(!__isactive_ci(ci)) return 0; if(ci->error) { /* Errors here are easy, fail and avoid scheduling a timeout */ ci->check->flags &= ~NP_RUNNING; dns_check_log_results(ci); __deactivate_ci(ci); return 0; } newe = eventer_alloc(); newe->mask = EVENTER_TIMER; gettimeofday(&now, NULL); p_int.tv_sec = check->timeout / 1000; p_int.tv_usec = (check->timeout % 1000) * 1000; add_timeval(now, p_int, &newe->whence); newe->closure = ci; newe->callback = dns_check_timeout; ci->timeout_event = newe; eventer_add(newe); return 0; }
noit_check_t * noit_fire_check(xmlNodePtr attr, xmlNodePtr config, const char **error) { char *target = NULL, *name = NULL, *module = NULL, *filterset = NULL; char *resolve_rtype = NULL; int timeout = 0, flags = NP_TRANSIENT, i, mod_cnt; noit_module_t *m; noit_check_t *c = NULL; xmlNodePtr a, co; noit_hash_table *conf_hash = NULL; noit_hash_table **moptions = NULL; for(a = attr->children; a; a = a->next) { if(!strcmp((char *)a->name, "target")) target = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "name")) name = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "module")) module = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "filterset")) filterset = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "timeout")) { char *timeout_str = (char *)xmlNodeGetContent(a); timeout = atoi(timeout_str); free(timeout_str); } else if(!strcmp((char *)a->name, "resolve_rtype")) resolve_rtype = (char *)xmlNodeGetContent(a); } m = noit_module_lookup(module); if(!m) { *error = "cannot find requested module"; goto error; } conf_hash = calloc(1, sizeof(*conf_hash)); if(config) { for(co = config->children; co; co = co->next) { char *name, *val; xmlChar *tmp_val; name = strdup((char *)co->name); tmp_val = xmlNodeGetContent(co); val = strdup(tmp_val ? (char *)tmp_val : ""); noit_hash_replace(conf_hash, name, strlen(name), val, free, free); xmlFree(tmp_val); } } mod_cnt = noit_check_registered_module_cnt(); if(mod_cnt > 0) { moptions = alloca(mod_cnt * sizeof(*moptions)); memset(moptions, 0, mod_cnt * sizeof(*moptions)); for(i=0; i<mod_cnt; i++) { const char *name; noit_conf_section_t checks; name = noit_check_registered_module(i); checks = noit_conf_get_section(NULL, "/noit/checks"); if(name) moptions[i] = noit_conf_get_namespaced_hash(checks, "config", name); } } if(!m->initiate_check) { *error = "that module cannot run checks"; goto error; } flags |= noit_calc_rtype_flag(resolve_rtype); c = calloc(1, sizeof(*c)); noit_check_update(c, target, name, filterset, conf_hash, moptions, 0, timeout, NULL, flags); c->module = strdup(module); uuid_generate(c->checkid); c->flags |= NP_DISABLED; /* this is hack to know we haven't run it yet */ if(NOIT_CHECK_SHOULD_RESOLVE(c)) noit_check_resolve(c); error: if(conf_hash) { noit_hash_destroy(conf_hash, free, free); free(conf_hash); } if(moptions) { for(i=0; i<mod_cnt; i++) { if(moptions[i]) { noit_hash_destroy(moptions[i], free, free); free(moptions[i]); } } } if(target) xmlFree(target); if(name) xmlFree(name); if(module) xmlFree(module); if(filterset) xmlFree(filterset); if (resolve_rtype) xmlFree(resolve_rtype); return c; }
static int rest_show_check(noit_http_rest_closure_t *restc, int npats, char **pats) { noit_http_session_ctx *ctx = restc->http_ctx; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; xmlDocPtr doc = NULL; xmlNodePtr node, root, attr, config, state, tmp, anode; uuid_t checkid; noit_check_t *check; char xpath[1024], *uuid_conf, *module, *value; int rv, cnt, error_code = 500; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; noit_hash_table *configh; if(npats != 2) goto error; rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]); if(rv == 0) goto not_found; if(rv < 0) goto error; noit_conf_xml_xpath(NULL, &xpath_ctxt); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto not_found; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt != 1) goto error; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error; doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL); xmlDocSetRootElement(doc, root); #define MYATTR(node,a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(node,a,n,b) \ _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(parent, node, a) do { \ xmlNodePtr anode = NULL; \ char *value = NULL; \ INHERIT(node, a, anode, value); \ if(value != NULL) { \ int clen, plen;\ const char *cpath, *apath; \ xmlNodePtr child; \ cpath = node ? (char *)xmlGetNodePath(node) : ""; \ apath = anode ? (char *)xmlGetNodePath(anode) : ""; \ clen = strlen(cpath); \ plen = strlen("/noit/checks"); \ child = xmlNewNode(NULL, (xmlChar *)#a); \ xmlNodeAddContent(child, (xmlChar *)value); \ if(!strncmp(cpath, apath, clen) && apath[clen] == '/') { \ } \ else { \ xmlSetProp(child, (xmlChar *)"inherited", (xmlChar *)apath+plen); \ } \ xmlAddChild(parent, child); \ } \ } while(0) attr = xmlNewNode(NULL, (xmlChar *)"attributes"); xmlAddChild(root, attr); SHOW_ATTR(attr,node,uuid); /* Name is odd, it falls back transparently to module */ if(!INHERIT(node, module, tmp, module)) module = NULL; xmlAddChild(attr, (tmp = xmlNewNode(NULL, (xmlChar *)"name"))); if(MYATTR(node, name, anode, value)) xmlNodeAddContent(tmp, (xmlChar *)value); else if(module) xmlNodeAddContent(tmp, (xmlChar *)module); SHOW_ATTR(attr,node,module); SHOW_ATTR(attr,node,target); SHOW_ATTR(attr,node,period); SHOW_ATTR(attr,node,timeout); SHOW_ATTR(attr,node,oncheck); SHOW_ATTR(attr,node,filterset); SHOW_ATTR(attr,node,disable); /* Add the config */ config = xmlNewNode(NULL, (xmlChar *)"config"); configh = noit_conf_get_hash(node, "config"); while(noit_hash_next(configh, &iter, &k, &klen, &data)) NODE_CONTENT(config, k, data); noit_hash_destroy(configh, free, free); free(configh); xmlAddChild(root, config); /* Add the state */ check = noit_poller_lookup(checkid); if(!check) { state = xmlNewNode(NULL, (xmlChar *)"state"); xmlSetProp(state, (xmlChar *)"error", (xmlChar *)"true"); } else state = noit_check_state_as_xml(check); xmlAddChild(root, state); noit_http_response_ok(ctx, "text/xml"); noit_http_response_xml(ctx, doc); noit_http_response_end(ctx); goto cleanup; not_found: noit_http_response_not_found(ctx, "text/html"); noit_http_response_end(ctx); goto cleanup; error: noit_http_response_standard(ctx, error_code, "ERROR", "text/html"); noit_http_response_end(ctx); goto cleanup; cleanup: if(pobj) xmlXPathFreeObject(pobj); if(doc) xmlFreeDoc(doc); return 0; }
void noit_poller_process_checks(const char *xpath) { int i, flags, cnt = 0; noit_conf_section_t *sec; __config_load_generation++; sec = noit_conf_get_sections(NULL, xpath, &cnt); for(i=0; i<cnt; i++) { void *vcheck; char uuid_str[37]; char target[256] = ""; char module[256] = ""; char name[256] = ""; char filterset[256] = ""; char oncheck[1024] = ""; int no_period = 0; int no_oncheck = 0; int period = 0, timeout = 0; noit_boolean disabled = noit_false, busted = noit_false; uuid_t uuid, out_uuid; noit_hash_table *options; #define NEXT(...) noitL(noit_stderr, __VA_ARGS__); continue #define MYATTR(type,a,...) noit_conf_get_##type(sec[i], "@" #a, __VA_ARGS__) #define INHERIT(type,a,...) \ noit_conf_get_##type(sec[i], "ancestor-or-self::node()/@" #a, __VA_ARGS__) if(!MYATTR(stringbuf, uuid, uuid_str, sizeof(uuid_str))) { noitL(noit_stderr, "check %d has no uuid\n", i+1); continue; } if(uuid_parse(uuid_str, uuid)) { noitL(noit_stderr, "check uuid: '%s' is invalid\n", uuid_str); continue; } if(!INHERIT(stringbuf, target, target, sizeof(target))) { noitL(noit_stderr, "check uuid: '%s' has no target\n", uuid_str); busted = noit_true; } if(!INHERIT(stringbuf, module, module, sizeof(module))) { noitL(noit_stderr, "check uuid: '%s' has no module\n", uuid_str); busted = noit_true; } if(!INHERIT(stringbuf, filterset, filterset, sizeof(filterset))) filterset[0] = '\0'; if(!MYATTR(stringbuf, name, name, sizeof(name))) strlcpy(name, module, sizeof(name)); if(!INHERIT(int, period, &period) || period == 0) no_period = 1; if(!INHERIT(stringbuf, oncheck, oncheck, sizeof(oncheck)) || !oncheck[0]) no_oncheck = 1; if(no_period && no_oncheck) { noitL(noit_stderr, "check uuid: '%s' has neither period nor oncheck\n", uuid_str); busted = noit_true; } if(!(no_period || no_oncheck)) { noitL(noit_stderr, "check uuid: '%s' has oncheck and period.\n", uuid_str); busted = noit_true; } if(!INHERIT(int, timeout, &timeout)) { noitL(noit_stderr, "check uuid: '%s' has no timeout\n", uuid_str); busted = noit_true; } if(!no_period && timeout >= period) { noitL(noit_stderr, "check uuid: '%s' timeout > period\n", uuid_str); timeout = period/2; } options = noit_conf_get_hash(sec[i], "config"); INHERIT(boolean, disable, &disabled); flags = 0; if(busted) flags |= (NP_UNCONFIG|NP_DISABLED); else if(disabled) flags |= NP_DISABLED; if(noit_hash_retrieve(&polls, (char *)uuid, UUID_SIZE, &vcheck)) { noit_check_t *existing_check = (noit_check_t *)vcheck; /* Once set, we can never change it. */ assert(!existing_check->module || !existing_check->module[0] || !strcmp(existing_check->module, module)); /* Only set it if it is not yet set */ if(!existing_check->module || !existing_check->module[0]) { if(existing_check->module) free(existing_check->module); existing_check->module = strdup(module); } noit_check_update(existing_check, target, name, filterset, options, period, timeout, oncheck[0] ? oncheck : NULL, flags); noitL(noit_debug, "reloaded uuid: %s\n", uuid_str); } else { noit_poller_schedule(target, module, name, filterset, options, period, timeout, oncheck[0] ? oncheck : NULL, flags, uuid, out_uuid); noitL(noit_debug, "loaded uuid: %s\n", uuid_str); } noit_hash_destroy(options, free, free); free(options); } if(sec) free(sec); }