root/src/noitd.c

Revision 304ec80b8cf842fc0abe5f9029790908b6455957, 7.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 1 week ago)

Convert to libmtev.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007-2010, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  * Copyright (c) 2015, Circonus, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials provided
15  *       with the distribution.
16  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
17  *       of its contributors may be used to endorse or promote products
18  *       derived from this software without specific prior written
19  *       permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "noit_config.h"
35 #include <mtev_defines.h>
36
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/mman.h>
44 #include <signal.h>
45 #ifdef HAVE_SYS_WAIT_H
46 #include <sys/wait.h>
47 #endif
48
49 #include <mtev_main.h>
50 #include <eventer/eventer.h>
51 #include <mtev_memory.h>
52 #include <mtev_log.h>
53 #include <mtev_hash.h>
54 #include <mtev_security.h>
55 #include <mtev_watchdog.h>
56 #include <mtev_lockfile.h>
57 #include <mtev_listener.h>
58 #include <mtev_console.h>
59 #include <mtev_rest.h>
60 #include <mtev_reverse_socket.h>
61 #include <mtev_capabilities_listener.h>
62 #include <mtev_conf.h>
63 #include <mtev_events_rest.h>
64
65 #include "noit_mtev_bridge.h"
66 #include "noit_jlog_listener.h"
67 #include "noit_check_rest.h"
68 #include "noit_livestream_listener.h"
69 #include "noit_module.h"
70 #include "noit_conf_checks.h"
71 #include "noit_filters.h"
72
73 #define APPNAME "noit"
74 #define CHILD_WATCHDOG_TIMEOUT 5 /*seconds*/
75
76 static char *config_file = ETC_DIR "/" APPNAME ".conf";
77 static char *xpath = NULL;
78 static const char *droptouser = NULL;
79 static const char *droptogroup = NULL;
80 static const char *chrootpath = NULL;
81 static int foreground = 0;
82 static int debug = 0;
83 static int strict_module_load = 0;
84 static char *glider = NULL;
85
86 #include "man/noitd.usage.h"
87 static void usage(const char *progname) {
88   printf("Usage for %s:\n", progname);
89 #ifdef NOITD_USAGE
90   assert(write(STDOUT_FILENO,
91                NOITD_USAGE,
92                sizeof(NOITD_USAGE)-1) == sizeof(NOITD_USAGE)-1);
93 #else
94   printf("\nError in usage, build problem.\n");
95 #endif
96   return;
97 }
98
99 void parse_clargs(int argc, char **argv) {
100   int c;
101   while((c = getopt(argc, argv, "x:Mhc:dDu:g:n:t:l:L:G:")) != EOF) {
102     switch(c) {
103       case 'x':
104         xpath = strdup(optarg);
105         foreground = 1;
106         break;
107       case 'G':
108         glider = strdup(optarg);
109         break;
110       case 'M':
111         strict_module_load = 1;
112         break;
113       case 'h':
114         usage(argv[0]);
115         exit(1);
116         break;
117       case 'l':
118         mtev_main_enable_log(optarg);
119         break;
120       case 'L':
121         mtev_main_disable_log(optarg);
122         break;
123       case 'n':
124         {
125           char *cp = optarg ? strchr(optarg, ':') : NULL;
126           if(!cp) mtev_listener_skip(optarg, 0);
127           else {
128             if(cp == optarg) optarg = NULL;
129             *cp++ = '\0';
130             mtev_listener_skip(optarg, atoi(cp));
131           }
132         }
133         break;
134       case 'u':
135         droptouser = strdup(optarg);
136         break;
137       case 'g':
138         droptogroup = strdup(optarg);
139         break;
140       case 't':
141         chrootpath = strdup(optarg);
142         break;
143       case 'c':
144         config_file = strdup(optarg);
145         break;
146       case 'D':
147         foreground++;
148         break;
149       case 'd':
150         debug++;
151         break;
152       default:
153         break;
154     }
155   }
156 }
157
158 static int __reload_needed = 0;
159 static void request_conf_reload(int sig) {
160   if(sig == SIGHUP) {
161     __reload_needed = 1;
162   }
163 }
164 static int notice_hup(eventer_t e, int mask, void *unused, struct timeval *now) {
165   if(__reload_needed) {
166     mtevL(noit_error, "SIGHUP received, performing reload\n");
167     if(mtev_conf_load(config_file) == -1) {
168       mtevL(noit_error, "Cannot load config: '%s'\n", config_file);
169       exit(-1);
170     }
171     noit_poller_reload(NULL);
172     __reload_needed = 0;
173   }
174   return 0;
175 }
176
177 static int noit_console_stopword(const char *word) {
178   return(!strcmp(word, "check") ||
179          !strcmp(word, "noit") ||
180          !strcmp(word, "filterset") ||
181          !strcmp(word, "config"));
182 }
183 const char *reverse_prefix = "noit/";
184 const char *reverse_prefix_cns[] = { "noit/", NULL };
185
186 static int child_main() {
187   eventer_t e;
188
189   /* Send out a birth notice. */
190   mtev_watchdog_child_heartbeat();
191   mtev_override_console_stopword(noit_console_stopword);
192
193   /* Load our config...
194    * to ensure it is current w.r.t. to this child starting */
195   if(mtev_conf_load(config_file) == -1) {
196     mtevL(noit_error, "Cannot load config: '%s'\n", config_file);
197     exit(2);
198   }
199   if(xpath) {
200     int cnt, i;
201     mtev_conf_section_t *parts = NULL;
202     parts = mtev_conf_get_sections(NULL, xpath, &cnt);
203     if(cnt == 0) exit(2);
204     for(i=0; i<cnt; i++) {
205       fprintf(stdout, "%d: ", i); fflush(stdout);
206       mtev_conf_write_section(parts[i], 1);
207     }
208     free(parts);
209     exit(0);
210   }
211
212   mtev_log_reopen_all();
213   mtevL(noit_notice, "process starting: %d\n", (int)getpid());
214   mtev_log_go_asynch();
215
216   signal(SIGHUP, request_conf_reload);
217
218   /* initialize the eventer */
219   if(eventer_init() == -1) {
220     mtevL(noit_stderr, "Cannot initialize eventer\n");
221     exit(-1);
222   }
223   /* rotation init requires, eventer_init() */
224   mtev_conf_log_init_rotate(APPNAME, mtev_false);
225
226   /* Setup our heartbeat */
227   mtev_watchdog_child_eventer_heartbeat();
228
229   e = eventer_alloc();
230   e->mask = EVENTER_RECURRENT;
231   e->callback = notice_hup;
232   eventer_add_recurrent(e);
233
234   /* Initialize all of our listeners */
235   mtev_console_init(APPNAME);
236   mtev_console_conf_init();
237   mtev_capabilities_listener_init();
238   mtev_http_rest_init();
239   mtev_reverse_socket_init(reverse_prefix, reverse_prefix_cns);
240   mtev_events_rest_init();
241   noit_console_conf_checks_init();
242   noit_jlog_listener_init();
243   noit_check_rest_init();
244   noit_filters_rest_init();
245   noit_livestream_listener_init();
246
247   mtev_dso_init();
248   noit_module_init();
249   mtev_dso_post_init();
250   if(strict_module_load &&
251      (mtev_dso_load_failures() > 0 || noit_module_load_failures() > 0)) {
252     mtevL(noit_stderr, "Failed to load some modules and -M given.\n");
253     exit(2);
254   }
255
256   mtev_listener_init(APPNAME);
257
258   /* Drop privileges */
259   mtev_conf_security_init(APPNAME, droptouser, droptogroup, chrootpath);
260
261   /* Prepare for launch... */
262   noit_filters_init();
263   noit_poller_init();
264
265   /* Write our log out, and setup a watchdog to write it out on change. */
266   mtev_conf_write_log(NULL);
267   mtev_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */
268   mtev_conf_watch_and_journal_watchdog(mtev_conf_write_log, NULL);
269
270   eventer_loop();
271   return 0;
272 }
273
274 int main(int argc, char **argv) {
275   int lock = MTEV_LOCK_OP_LOCK;
276   noit_mtev_bridge_init();
277   mtev_memory_init();
278   parse_clargs(argc, argv);
279   if (xpath) lock = MTEV_LOCK_OP_NONE;
280   return mtev_main(APPNAME, config_file, debug, foreground,
281                    lock, glider, droptouser, droptogroup,
282                    child_main);
283 }
Note: See TracBrowser for help on using the browser.