static void rest_test_check_result(struct check_test_closure *cl) { mtev_http_session_ctx *ctx = cl->restc->http_ctx; mtevL(nlerr, "Flushing check test result\n"); if(cl->restc->call_closure_free) cl->restc->call_closure_free(cl->restc->call_closure); cl->restc->call_closure_free = NULL; cl->restc->call_closure = NULL; cl->restc->fastpath = NULL; if(ctx) { eventer_t conne; if(cl->output == WANTS_JSON) { struct json_object *doc; const char *jsonstr; doc = noit_check_state_as_json(cl->check, 1); mtev_http_response_ok(ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(ctx, "\n", 1); json_object_put(doc); } else { xmlDocPtr doc = NULL; xmlNodePtr root, state; doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL); xmlDocSetRootElement(doc, root); state = noit_check_state_as_xml(cl->check, 1); xmlAddChild(root, state); mtev_http_response_ok(ctx, "text/xml"); mtev_http_response_xml(ctx, doc); xmlFreeDoc(doc); } mtev_http_response_end(ctx); conne = mtev_http_connection_event(mtev_http_session_connection(ctx)); if(conne) { // The event already exists, why re-add it? Did we want to update it? //eventer_add(conne); eventer_trigger(conne, EVENTER_READ | EVENTER_WRITE); } } noit_poller_free_check(cl->check); free(cl); }
static int rest_get_noit_config(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; char *xml = NULL; if(npats != 0) { mtev_http_response_server_error(ctx, "text/xml"); mtev_http_response_end(ctx); return 0; } xml = ingestor->get_noit_config(restc->remote_cn); if(xml == NULL) { char buff[1024]; snprintf(buff, sizeof(buff), "<error><remote_cn>%s</remote_cn>" "<row_count>%d</row_count></error>\n", restc->remote_cn, 0); mtev_http_response_append(ctx, buff, strlen(buff)); mtev_http_response_not_found(ctx, "text/xml"); } else { mtev_http_response_append(ctx, xml, strlen(xml)); mtev_http_response_ok(ctx, "text/xml"); } if(xml) free(xml); mtev_http_response_end(ctx); return 0; }
static int rest_show_feed(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; const char *err = "unknown error"; const char *jpath_with_sub; char jlogpath[PATH_MAX], *cp, **subs = NULL; int nsubs, i; mtev_log_stream_t feed; jlog_ctx *jctx = NULL; xmlDocPtr doc = NULL; xmlNodePtr root = NULL, subnodes; feed = mtev_log_stream_find("feed"); if(!feed) { err = "cannot find feed"; goto error; } jpath_with_sub = mtev_log_stream_get_path(feed); strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath)); cp = strchr(jlogpath, '('); if(cp) *cp = '\0'; jctx = jlog_new(jlogpath); if((nsubs = jlog_ctx_list_subscribers(jctx, &subs)) == -1) { err = jlog_ctx_err_string(jctx); goto error; } doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"feed", NULL); xmlDocSetRootElement(doc, root); subnodes = xmlNewNode(NULL, (xmlChar *)"subscribers"); for(i=0; i<nsubs; i++) { xmlNewChild(subnodes, NULL, (xmlChar *)"subscriber", (xmlChar *)subs[i]); } xmlAddChild(root, subnodes); mtev_http_response_ok(restc->http_ctx, "text/xml"); mtev_http_response_xml(restc->http_ctx, doc); mtev_http_response_end(restc->http_ctx); if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs); xmlFreeDoc(doc); jlog_ctx_close(jctx); return 0; error: if(doc) xmlFreeDoc(doc); if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs); mtev_http_response_server_error(ctx, "text/plain"); mtev_http_response_append(ctx, err, strlen(err)); mtev_http_response_end(ctx); if(jctx) jlog_ctx_close(jctx); return 0; }
static int mtev_rest_eventer_jobq(mtev_http_rest_closure_t *restc, int n, char **p) { const char *jsonstr; struct json_object *doc; doc = json_object_new_object(); eventer_jobq_process_each(json_spit_jobq, doc); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
static int mtev_rest_eventer_sockets(mtev_http_rest_closure_t *restc, int n, char **p) { const char *jsonstr; struct json_object *doc; doc = json_object_new_array(); eventer_foreach_fdevent(json_spit_event, doc); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
static int rest_cull_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { int rv; char cnt_str[32]; mtev_http_session_ctx *ctx = restc->http_ctx; rv = noit_filtersets_cull_unused(); if(rv > 0) mtev_conf_mark_changed(); snprintf(cnt_str, sizeof(cnt_str), "%d", rv); mtev_http_response_ok(ctx, "text/html"); mtev_http_response_header_set(ctx, "X-Filters-Removed", cnt_str); mtev_http_response_end(ctx); return 0; }
static int rest_show_checks_json(mtev_http_rest_closure_t *restc, int npats, char **pats) { const char *jsonstr; struct json_object *doc; doc = json_object_new_object(); noit_poller_do(json_check_accum, doc); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
int mtev_rest_eventer_logs(mtev_http_rest_closure_t *restc, int n, char **p) { char *endptr = NULL; const char *since_s, *last_s; const char *jsonstr; char errbuf[128]; unsigned long long since; int last = 0; struct json_object *doc; mtev_log_stream_t ls; mtev_http_request *req = mtev_http_session_request(restc->http_ctx); since_s = mtev_http_request_querystring(req, "since"); if(since_s) since = strtoull(since_s, &endptr, 10); last_s = mtev_http_request_querystring(req, "last"); if(last_s) last = atoi(last_s); assert(n==1); ls = mtev_log_stream_find(p[0]); if(!ls || strcmp(mtev_log_stream_get_type(ls),"memory")) goto not_found; doc = json_object_new_array(); if(endptr != since_s) mtev_log_memory_lines_since(ls, since, json_spit_log, doc); else mtev_log_memory_lines(ls, last, json_spit_log, doc); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; not_found: doc = json_object_new_object(); snprintf(errbuf, sizeof(errbuf), "log '%s' not found", p[0]); json_object_object_add(doc, "error", json_object_new_string(errbuf)); jsonstr = json_object_to_json_string(doc); mtev_http_response_not_found(restc->http_ctx, "application/json"); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
static int mtev_capabilities_rest(mtev_http_rest_closure_t *restc, int n, char **p) { mtev_capsvc_closure_t cl = { 0 }; const char *mtype = "application/xml"; if(n > 0 && !strcmp(p[0], ".json")) { mtev_capabilities_tobuff_json(&cl, NULL); mtype = "application/json"; } else mtev_capabilities_tobuff(&cl, NULL); if(!cl.buff) goto error; mtev_http_response_ok(restc->http_ctx, mtype); mtev_http_response_append(restc->http_ctx, cl.buff, cl.towrite); mtev_http_response_end(restc->http_ctx); free(cl.buff); return 0; error: mtev_http_response_server_error(restc->http_ctx, "text/html"); mtev_http_response_end(restc->http_ctx); return 0; }
static int rest_show_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlDocPtr doc = NULL; xmlNodePtr node, root; 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 = mtev_conf_get_section(NULL, xpath); if(!node) goto not_found; doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlCopyNode(node, 1); xmlDocSetRootElement(doc, root); mtev_http_response_ok(ctx, "text/xml"); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); goto cleanup; not_found: mtev_http_response_not_found(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/html"); mtev_http_response_end(ctx); goto cleanup; cleanup: if(doc) xmlFreeDoc(doc); return 0; }
static int rest_delete_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_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 = mtev_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(mtev_conf_write_file(NULL) != 0) mtevL(noit_error, "local config write failed\n"); mtev_conf_mark_changed(); mtev_http_response_ok(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; not_found: mtev_http_response_not_found(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/html"); mtev_http_response_end(ctx); goto cleanup; cleanup: return 0; }
static int rest_show_check_json(mtev_http_rest_closure_t *restc, uuid_t checkid) { noit_check_t *check; struct json_object *doc; const char *jsonstr; check = noit_poller_lookup(checkid); if(!check) { mtev_http_response_not_found(restc->http_ctx, "application/json"); mtev_http_response_end(restc->http_ctx); return 0; } doc = noit_check_state_as_json(check, 1); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
static int rest_httptrap_handler(mtev_http_rest_closure_t *restc, int npats, char **pats) { int mask, complete = 0, cnt; struct rest_json_payload *rxc = NULL; const char *error = "internal error", *secret = NULL; mtev_http_session_ctx *ctx = restc->http_ctx; char json_out[128]; noit_check_t *check; uuid_t check_id; if(npats != 2) { error = "bad uri"; goto error; } if(uuid_parse(pats[0], check_id)) { error = "uuid parse error"; goto error; } if(restc->call_closure == NULL) { httptrap_closure_t *ccl; const char *delimiter = NULL; rxc = restc->call_closure = calloc(1, sizeof(*rxc)); rxc->delimiter = DEFAULT_HTTPTRAP_DELIMITER; check = noit_poller_lookup(check_id); if(!check || strcmp(check->module, "httptrap")) { error = "no such httptrap check"; goto error; } (void)mtev_hash_retr_str(check->config, "secret", strlen("secret"), &secret); if(!secret) secret = ""; if(strcmp(pats[1], secret)) { error = "secret mismatch"; goto error; } (void)mtev_hash_retr_str(check->config, "delimiter", strlen("delimiter"), &delimiter); if(delimiter && *delimiter) rxc->delimiter = *delimiter; rxc->check = check; ccl = check->closure; if(!ccl) { error = "noitd is booting, try again in a bit"; goto error; } rxc->parser = yajl_alloc(&httptrap_yajl_callbacks, NULL, rxc); rxc->depth = -1; yajl_config(rxc->parser, yajl_allow_comments, 1); yajl_config(rxc->parser, yajl_dont_validate_strings, 1); yajl_config(rxc->parser, yajl_allow_trailing_garbage, 1); yajl_config(rxc->parser, yajl_allow_partial_values, 1); restc->call_closure_free = rest_json_payload_free; } else rxc = restc->call_closure; /* flip threads */ { mtev_http_connection *conn = mtev_http_session_connection(ctx); eventer_t e = mtev_http_connection_event(conn); if(e) { pthread_t tgt = CHOOSE_EVENTER_THREAD_FOR_CHECK(rxc->check); if(!pthread_equal(e->thr_owner, tgt)) { e->thr_owner = tgt; return EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION; } } } rxc = rest_get_json_upload(restc, &mask, &complete); if(rxc == NULL && !complete) return mask; if(!rxc) goto error; if(rxc->error) goto error; cnt = push_payload_at_check(rxc); mtev_http_response_ok(ctx, "application/json"); snprintf(json_out, sizeof(json_out), "{ \"stats\": %d }", cnt); mtev_http_response_append(ctx, json_out, strlen(json_out)); mtev_http_response_end(ctx); return 0; error: mtev_http_response_server_error(ctx, "application/json"); mtev_http_response_append(ctx, "{ error: \"", 10); if(rxc && rxc->error) error = rxc->error; mtev_http_response_append(ctx, error, strlen(error)); mtev_http_response_append(ctx, "\" }", 3); mtev_http_response_end(ctx); return 0; }
static int rest_add_feed(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlXPathObjectPtr pobj = NULL; xmlDocPtr doc = NULL, indoc = NULL; xmlNodePtr node, root; acceptor_closure_t *ac = restc->ac; int error_code = 500, complete = 0, mask = 0, rv; const char *error = "internal error", *logname; char *name, *copy_from; mtev_log_stream_t feed; const char *jpath_with_sub; char jlogpath[PATH_MAX], *cp; jlog_ctx *jctx = NULL; jlog_id chkpt; if(npats != 0) goto error; indoc = rest_get_xml_upload(restc, &mask, &complete); if(!complete) return mask; if(indoc == NULL) { error = "xml parse error"; goto error; } if(!mtev_hash_retr_str(ac->config, "log_transit_feed_name", strlen("log_transit_feed_name"), &logname)) { goto error; } feed = mtev_log_stream_find("feed"); if(!feed) { error = "couldn't find feed"; goto error; } jpath_with_sub = mtev_log_stream_get_path(feed); strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath)); cp = strchr(jlogpath, '('); if(cp) *cp = '\0'; node = xmlDocGetRootElement(indoc); name = (char*)xmlGetProp(node, (xmlChar*)"name"); copy_from = (char*)xmlGetProp(node, (xmlChar*)"checkpoint_copy"); jctx = jlog_new(jlogpath); if (!jctx) { error = "couldn't open logpath"; goto error; } if (!jlog_get_checkpoint(jctx, name, &chkpt)) { error = "subscriber already exists, can't add"; goto error; } if (copy_from) { rv = jlog_ctx_add_subscriber_copy_checkpoint(jctx, name, copy_from); } else { rv = jlog_ctx_add_subscriber(jctx, name, JLOG_END); } if (rv == -1) { error = "couldn't add subscriber"; goto error; } mtev_http_response_ok(restc->http_ctx, "text/xml"); mtev_http_response_end(restc->http_ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/xml"); doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL); xmlDocSetRootElement(doc, root); xmlNodeAddContent(root, (xmlChar *)error); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); cleanup: if (jctx) { jlog_ctx_close(jctx); } if(pobj) xmlXPathFreeObject(pobj); if(doc) xmlFreeDoc(doc); return 0; }