health_cmdapi.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //
  2. // Created by Christopher on 11/12/18.
  3. //
  4. #include "health_cmdapi.h"
  5. /**
  6. * Free Silencers
  7. *
  8. * Clean the silencer structure
  9. *
  10. * @param t is the structure that will be cleaned.
  11. */
  12. void free_silencers(SILENCER *t) {
  13. if (!t) return;
  14. if (t->next) free_silencers(t->next);
  15. debug(D_HEALTH, "HEALTH command API: Freeing silencer %s:%s:%s:%s:%s", t->alarms,
  16. t->charts, t->contexts, t->hosts, t->families);
  17. simple_pattern_free(t->alarms_pattern);
  18. simple_pattern_free(t->charts_pattern);
  19. simple_pattern_free(t->contexts_pattern);
  20. simple_pattern_free(t->hosts_pattern);
  21. simple_pattern_free(t->families_pattern);
  22. freez(t->alarms);
  23. freez(t->charts);
  24. freez(t->contexts);
  25. freez(t->hosts);
  26. freez(t->families);
  27. freez(t);
  28. return;
  29. }
  30. /**
  31. * Silencers to JSON Entry
  32. *
  33. * Fill the buffer with the other values given.
  34. *
  35. * @param wb a pointer to the output buffer
  36. * @param var the json variable
  37. * @param val the json value
  38. * @param hasprev has it a previous value?
  39. *
  40. * @return
  41. */
  42. int health_silencers2json_entry(BUFFER *wb, char* var, char* val, int hasprev) {
  43. if (val) {
  44. buffer_sprintf(wb, "%s\n\t\t\t\"%s\": \"%s\"", (hasprev)?",":"", var, val);
  45. return 1;
  46. } else {
  47. return hasprev;
  48. }
  49. }
  50. /**
  51. * Silencer to JSON
  52. *
  53. * Write the silencer values using JSON format inside a buffer.
  54. *
  55. * @param wb is the buffer to write the silencers.
  56. */
  57. void health_silencers2json(BUFFER *wb) {
  58. buffer_sprintf(wb, "{\n\t\"all\": %s,"
  59. "\n\t\"type\": \"%s\","
  60. "\n\t\"silencers\": [",
  61. (silencers->all_alarms)?"true":"false",
  62. (silencers->stype == STYPE_NONE)?"None":((silencers->stype == STYPE_DISABLE_ALARMS)?"DISABLE":"SILENCE"));
  63. SILENCER *silencer;
  64. int i = 0, j = 0;
  65. for(silencer = silencers->silencers; silencer ; silencer = silencer->next) {
  66. if(likely(i)) buffer_strcat(wb, ",");
  67. buffer_strcat(wb, "\n\t\t{");
  68. j=health_silencers2json_entry(wb, HEALTH_ALARM_KEY, silencer->alarms, j);
  69. j=health_silencers2json_entry(wb, HEALTH_CHART_KEY, silencer->charts, j);
  70. j=health_silencers2json_entry(wb, HEALTH_CONTEXT_KEY, silencer->contexts, j);
  71. j=health_silencers2json_entry(wb, HEALTH_HOST_KEY, silencer->hosts, j);
  72. health_silencers2json_entry(wb, HEALTH_FAMILIES_KEY, silencer->families, j);
  73. j=0;
  74. buffer_strcat(wb, "\n\t\t}");
  75. i++;
  76. }
  77. if(likely(i)) buffer_strcat(wb, "\n\t");
  78. buffer_strcat(wb, "]\n}\n");
  79. }
  80. /**
  81. * Silencer to FILE
  82. *
  83. * Write the silencer buffer to a file.
  84. * @param wb
  85. */
  86. void health_silencers2file(BUFFER *wb) {
  87. if (wb->len == 0) return;
  88. FILE *fd = fopen(silencers_filename, "wb");
  89. if(fd) {
  90. size_t written = (size_t)fprintf(fd, "%s", wb->buffer) ;
  91. if (written == wb->len ) {
  92. info("Silencer changes written to %s", silencers_filename);
  93. }
  94. fclose(fd);
  95. return;
  96. }
  97. error("Silencer changes could not be written to %s. Error %s", silencers_filename, strerror(errno));
  98. }
  99. /**
  100. * Request V1 MGMT Health
  101. *
  102. * Function called by api to management the health.
  103. *
  104. * @param host main structure with client information!
  105. * @param w is the structure with all information of the client request.
  106. * @param url is the url that netdata is working
  107. *
  108. * @return It returns 200 on success and another code otherwise.
  109. */
  110. int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, char *url) {
  111. int ret;
  112. (void) host;
  113. BUFFER *wb = w->response.data;
  114. buffer_flush(wb);
  115. wb->contenttype = CT_TEXT_PLAIN;
  116. buffer_flush(w->response.data);
  117. //Local instance of the silencer
  118. SILENCER *silencer = NULL;
  119. int config_changed = 1;
  120. if (!w->auth_bearer_token) {
  121. buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR);
  122. ret = HTTP_RESP_FORBIDDEN;
  123. } else {
  124. debug(D_HEALTH, "HEALTH command API: Comparing secret '%s' to '%s'", w->auth_bearer_token, api_secret);
  125. if (strcmp(w->auth_bearer_token, api_secret)) {
  126. buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR);
  127. ret = HTTP_RESP_FORBIDDEN;
  128. } else {
  129. while (url) {
  130. char *value = mystrsep(&url, "&");
  131. if (!value || !*value) continue;
  132. char *key = mystrsep(&value, "=");
  133. if (!key || !*key) continue;
  134. if (!value || !*value) continue;
  135. debug(D_WEB_CLIENT, "%llu: API v1 health query param '%s' with value '%s'", w->id, key, value);
  136. // name and value are now the parameters
  137. if (!strcmp(key, "cmd")) {
  138. if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCEALL)) {
  139. silencers->all_alarms = 1;
  140. silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
  141. buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCEALL);
  142. } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLEALL)) {
  143. silencers->all_alarms = 1;
  144. silencers->stype = STYPE_DISABLE_ALARMS;
  145. buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLEALL);
  146. } else if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCE)) {
  147. silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
  148. buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCE);
  149. } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLE)) {
  150. silencers->stype = STYPE_DISABLE_ALARMS;
  151. buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLE);
  152. } else if (!strcmp(value, HEALTH_CMDAPI_CMD_RESET)) {
  153. silencers->all_alarms = 0;
  154. silencers->stype = STYPE_NONE;
  155. free_silencers(silencers->silencers);
  156. silencers->silencers = NULL;
  157. buffer_strcat(wb, HEALTH_CMDAPI_MSG_RESET);
  158. } else if (!strcmp(value, HEALTH_CMDAPI_CMD_LIST)) {
  159. w->response.data->contenttype = CT_APPLICATION_JSON;
  160. health_silencers2json(wb);
  161. config_changed=0;
  162. }
  163. } else {
  164. silencer = health_silencers_addparam(silencer, key, value);
  165. }
  166. }
  167. if (likely(silencer)) {
  168. health_silencers_add(silencer);
  169. buffer_strcat(wb, HEALTH_CMDAPI_MSG_ADDED);
  170. if (silencers->stype == STYPE_NONE) {
  171. buffer_strcat(wb, HEALTH_CMDAPI_MSG_STYPEWARNING);
  172. }
  173. }
  174. if (unlikely(silencers->stype != STYPE_NONE && !silencers->all_alarms && !silencers->silencers)) {
  175. buffer_strcat(wb, HEALTH_CMDAPI_MSG_NOSELECTORWARNING);
  176. }
  177. ret = HTTP_RESP_OK;
  178. }
  179. }
  180. w->response.data = wb;
  181. buffer_no_cacheable(w->response.data);
  182. if (ret == HTTP_RESP_OK && config_changed) {
  183. BUFFER *jsonb = buffer_create(200, &netdata_buffers_statistics.buffers_health);
  184. health_silencers2json(jsonb);
  185. health_silencers2file(jsonb);
  186. buffer_free(jsonb);
  187. }
  188. return ret;
  189. }