static int rest_delete_filter(noit_http_rest_closure_t *restc, int npats, char **pats) { noit_http_session_ctx *ctx = restc->http_ctx; xmlNodePtr node; char xpath[1024]; int error_code = 500; if(npats != 2) goto error; snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]", pats[0], pats[1]); node = noit_conf_get_section(NULL, xpath); if(!node) goto not_found; if(noit_filter_remove(node) == 0) goto not_found; CONF_REMOVE(node); xmlUnlinkNode(node); xmlFreeNode(node); if(noit_conf_write_file(NULL) != 0) noitL(noit_error, "local config write failed\n"); noit_conf_mark_changed(); noit_http_response_ok(ctx, "text/html"); 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: return 0; }
static int replace_config(mtev_console_closure_t ncct, mtev_conf_t_userdata_t *info, const char *name, const char *value) { int i, cnt, rv = -1, active = 0; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; xmlNodePtr node, confignode; char xpath[1024], *path; path = info->path; if(!strcmp(path, "/")) path = ""; mtev_conf_xml_xpath(NULL, &xpath_ctxt); /* Only if checks will fixate this attribute shall we check for * child <check> nodes. * NOTE: this return nothing and "seems" okay if we are _in_ * a <check> node. That case is handled below. */ snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { uuid_t checkid; node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check && NOIT_CHECK_LIVE(check)) active++; } } if(pobj) xmlXPathFreeObject(pobj); #ifdef UNSAFE_RECONFIG snprintf(xpath, sizeof(xpath), "/noit/%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt != 1) { nc_printf(ncct, "Internal error: context node disappeared\n"); goto out; } node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); if(strcmp((const char *)node->name, "check")) { uuid_t checkid; /* Detect if we are actually a <check> node and attempting to * change something we shouldn't. * This is the counterpart noted above. */ if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(NOIT_CHECK_LIVE(check)) active++; } } if(active) { nc_printf(ncct, "Cannot set '%s', it would effect %d live check(s)\n", name, active); goto out; } if(pobj) xmlXPathFreeObject(pobj); #endif /* Here we want to remove /noit/path/config/name */ snprintf(xpath, sizeof(xpath), "/noit/%s/config/%s", path, name); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) > 0) { xmlNodePtr toremove; toremove = xmlXPathNodeSetItem(pobj->nodesetval, 0); CONF_REMOVE(toremove); xmlUnlinkNode(toremove); } /* TODO: if there are no more children of config, remove config? */ if(value) { if(pobj) xmlXPathFreeObject(pobj); /* He we create config if needed and place a child node under it */ snprintf(xpath, sizeof(xpath), "/noit/%s/config", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) == 0) { if(pobj) xmlXPathFreeObject(pobj); snprintf(xpath, sizeof(xpath), "/noit/%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { nc_printf(ncct, "Node disappeared from under you!\n"); goto out; } confignode = xmlNewChild(xmlXPathNodeSetItem(pobj->nodesetval, 0), NULL, (xmlChar *)"config", NULL); if(confignode == NULL) { nc_printf(ncct, "Error creating config child node.\n"); goto out; } } else confignode = xmlXPathNodeSetItem(pobj->nodesetval, 0); mtevAssert(confignode); /* Now we create a child */ xmlNewChild(confignode, NULL, (xmlChar *)name, (xmlChar *)value); CONF_DIRTY(confignode); } mtev_conf_mark_changed(); rv = 0; out: if(pobj) xmlXPathFreeObject(pobj); return rv; }
static int noit_console_config_nocheck(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { int i, cnt; const char *err = "internal error"; mtev_conf_t_userdata_t *info; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; char xpath[1024]; uuid_t checkid; mtev_conf_xml_xpath(NULL, &xpath_ctxt); if(argc < 1) { nc_printf(ncct, "requires one argument\n"); return -1; } info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA); if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, argv[0])) { 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)) { err = "no checks found"; goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { xmlNodePtr node; char *uuid_conf; node = (mtev_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")); } else { if(argc > 1) { int j; for(j=1;j<argc;j++) xmlUnsetProp(node, (xmlChar *)argv[j]); noit_conf_check_bump_seq(node); CONF_DIRTY(node); } else { nc_printf(ncct, "descheduling %s\n", uuid_conf); noit_poller_deschedule(checkid, mtev_true); CONF_REMOVE(node); xmlUnlinkNode(node); } mtev_conf_mark_changed(); } xmlFree(uuid_conf); } if(argc > 1) { noit_poller_process_checks(xpath); noit_poller_reload(xpath); } nc_printf(ncct, "rebuilding causal map...\n"); noit_poller_make_causal_map(); if(pobj) xmlXPathFreeObject(pobj); return 0; bad: if(pobj) xmlXPathFreeObject(pobj); nc_printf(ncct, "%s\n", err); return -1; }
int noit_filtersets_cull_unused() { mtev_hash_table active = MTEV_HASH_EMPTY; char *buffer = NULL; mtev_conf_section_t *declares; int i, n_uses = 0, n_declares = 0, removed = 0; const char *declare_xpath = "//filterset[@name and not (@cull='false')]"; declares = mtev_conf_get_sections(NULL, declare_xpath, &n_declares); if(declares) { /* store all unit filtersets used */ for(i=0;i<n_declares;i++) { if(!buffer) buffer = malloc(128); if(mtev_conf_get_stringbuf(declares[i], "@name", buffer, 128)) { if(mtev_hash_store(&active, buffer, strlen(buffer), declares[i])) { buffer = NULL; } else { void *vnode = NULL; /* We've just hit a duplicate.... check to see if there's an existing * entry and if there is, load the latest one and delete the old * one. */ mtev_hash_retrieve(&active, buffer, strlen(buffer), &vnode); if (vnode) { noit_filter_compile_add(declares[i]); CONF_REMOVE(vnode); xmlUnlinkNode(vnode); xmlFreeNode(vnode); removed++; if(mtev_hash_replace(&active, buffer, strlen(buffer), declares[i], free, NULL)) { buffer = NULL; } } } } } if(buffer) free(buffer); free(declares); } n_uses = noit_poller_do(filterset_accum, &active); if(n_uses > 0 && mtev_hash_size(&active) > 0) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *filter_name; int filter_name_len; void *vnode; while(mtev_hash_next(&active, &iter, &filter_name, &filter_name_len, &vnode)) { if(noit_filter_remove(vnode)) { CONF_REMOVE(vnode); xmlUnlinkNode(vnode); xmlFreeNode(vnode); removed++; } } } mtev_hash_destroy(&active, free, NULL); return removed; }
static int noit_console_filter_configure(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { xmlNodePtr parent, fsnode = NULL; int rv = -1; mtev_conf_t_userdata_t *info; char xpath[1024]; info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA); if(!info) { nc_printf(ncct, "internal error\n"); goto cleanup; } if(strncmp(info->path, "/filtersets/", strlen("/filtersets/")) && strcmp(info->path, "/filtersets")) { nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n", info->path); goto cleanup; } if(argc != 1) { nc_printf(ncct, "filterset requires one argument\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "/%s", info->path); parent = mtev_conf_get_section(NULL, xpath); if(!parent) { nc_printf(ncct, "internal error, can't final current working path\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]); fsnode = mtev_conf_get_section(parent, xpath); if(closure) { int removed; removed = noit_filter_remove(fsnode); nc_printf(ncct, "%sremoved filterset '%s'\n", removed ? "" : "failed to ", argv[0]); if(removed) { CONF_REMOVE(fsnode); xmlUnlinkNode(fsnode); xmlFreeNode(fsnode); } rv = !removed; goto cleanup; } if(!fsnode) { void *vfs; nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]); LOCKFS(); if(mtev_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) { UNLOCKFS(); nc_printf(ncct, "filter of the same name already exists\n"); goto cleanup; } UNLOCKFS(); /* Fine the parent path */ fsnode = xmlNewNode(NULL, (xmlChar *)"filterset"); xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]); xmlAddChild(parent, fsnode); nc_printf(ncct, "created new filterset\n"); } if(info) { char *xmlpath = NULL; free(info->path); xmlpath = (char *)xmlGetNodePath(fsnode); info->path = strdup(xmlpath + strlen("/noit")); free(xmlpath); strlcpy(info->filter_name, argv[0], sizeof(info->filter_name)); if(state) { mtev_console_state_push_state(ncct, state); mtev_console_state_init(ncct); } } cleanup: return rv; }