root/src/noit_check_rest.c

Revision 02569455fdf31dd93db18514b0b4cda5d5181ff7, 8.1 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

work on #171, getting check info works

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34 #include <assert.h>
35 #include <libxml/parser.h>
36 #include <libxml/tree.h>
37 #include <libxml/xpath.h>
38 #include "noit_listener.h"
39 #include "noit_http.h"
40 #include "noit_rest.h"
41 #include "noit_check.h"
42 #include "noit_check_tools.h"
43 #include "noit_conf.h"
44 #include "noit_conf_private.h"
45
46 static int
47 rest_host_check(noit_http_rest_closure_t *restc,
48                 int npats, char **pats) {
49   noit_http_session_ctx *ctx = restc->http_ctx;
50   xmlXPathObjectPtr pobj = NULL;
51   xmlXPathContextPtr xpath_ctxt = NULL;
52   xmlDocPtr doc = NULL;
53   xmlNodePtr node, root, attr, config, state, tmp, anode, metrics;
54   uuid_t checkid;
55   noit_check_t *check;
56   char xpath[1024], *uuid_conf, *module, *value;
57   int rv, cnt;
58   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
59   const char *k;
60   int klen;
61   void *data;
62   noit_hash_table *configh;
63
64   if(npats != 2) goto error;
65
66   rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]);
67   if(rv == 0) goto not_found;
68   if(rv < 0) goto error;
69
70   noit_conf_xml_xpath(NULL, &xpath_ctxt);
71   pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
72   if(!pobj || pobj->type != XPATH_NODESET ||
73      xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto not_found;
74   cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
75   if(cnt != 1) goto error;
76
77   node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
78   uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
79   if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error;
80
81   doc = xmlNewDoc((xmlChar *)"1.0");
82   root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL);
83   xmlDocSetRootElement(doc, root);
84
85 #define MYATTR(node,a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b))
86 #define INHERIT(node,a,n,b) \
87   _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b))
88 #define SHOW_ATTR(parent, node, a) do { \
89   xmlNodePtr anode = NULL; \
90   char *value = NULL; \
91   INHERIT(node, a, anode, value); \
92   if(value != NULL) { \
93     int clen, plen;\
94     const char *cpath, *apath; \
95     xmlNodePtr child; \
96     cpath = node ? (char *)xmlGetNodePath(node) : ""; \
97     apath = anode ? (char *)xmlGetNodePath(anode) : ""; \
98     clen = strlen(cpath); \
99     plen = strlen("/noit/checks"); \
100     child = xmlNewNode(NULL, (xmlChar *)#a); \
101     xmlNodeAddContent(child, (xmlChar *)value); \
102     if(!strncmp(cpath, apath, clen) && apath[clen] == '/') { \
103     } \
104     else { \
105       xmlSetProp(child, (xmlChar *)"inherited", (xmlChar *)apath+plen); \
106     } \
107     xmlAddChild(parent, child); \
108   } \
109 } while(0)
110 #define NODE_CONTENT(parent, k, v) do { \
111   xmlNodePtr tmp; \
112   if(v) { \
113     tmp = xmlNewNode(NULL, (xmlChar *)(k)); \
114     xmlNodeAddContent(tmp, (xmlChar *)(v)); \
115     xmlAddChild(parent, tmp); \
116   } \
117 } while(0)
118
119   attr = xmlNewNode(NULL, (xmlChar *)"attributes");
120   xmlAddChild(root, attr);
121
122   /* Name is odd, it falls back transparently to module */
123   if(!INHERIT(node, module, tmp, module)) module = NULL;
124   xmlAddChild(attr, (tmp = xmlNewNode(NULL, (xmlChar *)"name")));
125   if(MYATTR(node, name, anode, value))
126     xmlNodeAddContent(tmp, (xmlChar *)value);
127   else if(module)
128     xmlNodeAddContent(tmp, (xmlChar *)module);
129
130   SHOW_ATTR(attr,node,module);
131   SHOW_ATTR(attr,node,target);
132   SHOW_ATTR(attr,node,period);
133   SHOW_ATTR(attr,node,timeout);
134   SHOW_ATTR(attr,node,oncheck);
135   SHOW_ATTR(attr,node,filterset);
136   SHOW_ATTR(attr,node,disable);
137
138   /* Add the config */
139   config = xmlNewNode(NULL, (xmlChar *)"config");
140   configh = noit_conf_get_hash(node, "config");
141   while(noit_hash_next(configh, &iter, &k, &klen, &data))
142     NODE_CONTENT(config, k, data);
143   noit_hash_destroy(configh, free, free);
144   free(configh);
145   xmlAddChild(root, config);
146
147   /* Add the state */
148   xmlAddChild(root, (state = xmlNewNode(NULL, (xmlChar *)"state")));
149   check = noit_poller_lookup(checkid);
150   if(!check)
151     xmlSetProp(state, (xmlChar *)"error", (xmlChar *)"true");
152   else {
153     stats_t *c = &check->stats.current;
154     NODE_CONTENT(state, "running", NOIT_CHECK_RUNNING(check)?"true":"false");
155     NODE_CONTENT(state, "killed", NOIT_CHECK_KILLED(check)?"true":"false");
156     NODE_CONTENT(state, "configured",
157                  NOIT_CHECK_CONFIGURED(check)?"true":"false");
158     NODE_CONTENT(state, "disabled", NOIT_CHECK_DISABLED(check)?"true":"false");
159     xmlAddChild(state, (tmp = xmlNewNode(NULL, (xmlChar *)"last_run")));
160     if(check->stats.current.whence.tv_sec) {
161       struct timeval f = check->stats.current.whence;
162       struct timeval n;
163       char timestr[20];
164       gettimeofday(&n, NULL);
165       snprintf(timestr, sizeof(timestr), "%0.3f",
166                n.tv_sec + (n.tv_usec / 1000000.0));
167       xmlSetProp(tmp, (xmlChar *)"now", (xmlChar *)timestr);
168       snprintf(timestr, sizeof(timestr), "%0.3f",
169                f.tv_sec + (f.tv_usec / 1000000.0));
170       xmlNodeAddContent(tmp, (xmlChar *)timestr);
171     }
172     if(c->available) { /* truth here means the check has been run */
173       char buff[20];
174       snprintf(buff, sizeof(buff), "%0.3f", (float)c->duration/1000.0);
175       NODE_CONTENT(state, "runtime", buff);
176     }
177     NODE_CONTENT(state, "availability",
178                  noit_check_available_string(c->available));
179     NODE_CONTENT(state, "state", noit_check_state_string(c->state));
180     NODE_CONTENT(state, "status", c->status ? c->status : "");
181     memset(&iter, 0, sizeof(iter));
182     xmlAddChild(state, (metrics = xmlNewNode(NULL, (xmlChar *)"metrics")));
183     while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) {
184       char buff[256];
185       metric_t *m = (metric_t *)data;
186       xmlAddChild(metrics, (tmp = xmlNewNode(NULL, (xmlChar *)m->metric_name)));
187       buff[0] = m->metric_type; buff[1] = '\0';
188       xmlSetProp(tmp, (xmlChar *)"type", (xmlChar *)buff);
189       if(m->metric_value.s) {
190         int rv;
191         rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m);
192         if(rv < 0)
193           xmlSetProp(tmp, (xmlChar *)"error", (xmlChar *)"unknown type");
194         else
195           xmlNodeAddContent(tmp, (xmlChar *)buff);
196       }
197     }
198
199   }
200   noit_http_response_ok(ctx, "text/xml");
201   noit_http_response_xml(ctx, doc);
202   noit_http_response_end(ctx);
203   goto cleanup;
204
205  not_found:
206   noit_http_response_not_found(ctx, "text/html");
207   noit_http_response_end(ctx);
208   goto cleanup;
209
210  error:
211   noit_http_response_server_error(ctx, "text/html");
212   noit_http_response_end(ctx);
213   goto cleanup;
214
215  cleanup:
216   if(pobj) xmlXPathFreeObject(pobj);
217   if(doc) xmlFreeDoc(doc);
218   return 0;
219 }
220
221 void
222 noit_check_rest_init() {
223   assert(noit_http_rest_register(
224     "GET",
225     "/checks/",
226     "^show(/.*)(?<=/)([0-9a-fA-F]{4}(?:[0-9a-fA-F]{4}-){4}[0-9a-fA-F]{12})$",
227     rest_host_check
228   ) == 0);
229 }
230
Note: See TracBrowser for help on using the browser.