1 #include <dotconf.h>
2 #include <string.h>
3 #include <gmetad.h>
4 #include <ganglia.h>
5 #include "conf.h"
6
7 /* Variables that get filled in by configuration file */
8 extern Source_t root;
9 extern hash_t *sources;
10
11 gmetad_config_t gmetad_config;
12
13 #define GANGLIA_HOSTNAME_LEN 128
14
DOTCONF_CB(cb_gridname)15 static DOTCONF_CB(cb_gridname)
16 {
17 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
18 debug_msg("Grid name %s", cmd->data.str);
19 c->gridname = strdup(cmd->data.str);
20 return NULL;
21 }
22
DOTCONF_CB(cb_authority)23 static DOTCONF_CB(cb_authority)
24 {
25 /* See gmetad.h for why we record strings this way. */
26 debug_msg("Grid authority %s", cmd->data.str);
27 root.authority_ptr = 0;
28 strcpy(root.strings, cmd->data.str);
29 root.stringslen += strlen(root.strings) + 1;
30 return NULL;
31 }
32
DOTCONF_CB(cb_all_trusted)33 static DOTCONF_CB(cb_all_trusted)
34 {
35 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
36 debug_msg("All hosts are trusted!");
37 c->all_trusted = 1;
38 return NULL;
39 }
40
DOTCONF_CB(cb_trusted_hosts)41 static DOTCONF_CB(cb_trusted_hosts)
42 {
43 int i,rv;
44 llist_entry *le;
45 struct sockaddr_in sa;
46 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
47
48 for (i = 0; i < cmd->arg_count; i++)
49 {
50 le = (llist_entry *)malloc(sizeof(llist_entry));
51 rv = g_gethostbyname( cmd->data.list[i], &sa, NULL);
52 if (!rv) {
53 err_msg("Warning: we failed to resolve trusted host name %s", cmd->data.list[i]);
54 continue;
55 }
56 le->val = (char*) malloc(GANGLIA_HOSTNAME_LEN);
57 my_inet_ntop(AF_INET, &sa.sin_addr, le->val, GANGLIA_HOSTNAME_LEN);
58 llist_add(&(c->trusted_hosts), le);
59 }
60 return NULL;
61 }
62
DOTCONF_CB(cb_RRAs)63 static DOTCONF_CB(cb_RRAs)
64 {
65 int i;
66 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
67 c->num_RRAs = cmd->arg_count;
68 for(i = 0; i < c->num_RRAs; i++)
69 {
70 c->RRAs[i] = strdup(cmd->data.list[i]);
71 }
72 return NULL;
73 }
74
DOTCONF_CB(cb_data_source)75 static DOTCONF_CB(cb_data_source)
76 {
77 unsigned int i;
78 data_source_list_t *dslist;
79 datum_t key, val, *find;
80 int port, rv=0;
81 unsigned long step;
82 unsigned int source_index=0;
83 char *p, *str;
84 char *endptr;
85 struct sockaddr_in sa;
86 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
87
88 source_index++;
89
90 debug_msg("Datasource = [%s]", cmd->data.list[0]);
91
92 dslist = (data_source_list_t *) malloc ( sizeof(data_source_list_t) );
93 if(!dslist)
94 {
95 err_quit("Unable to malloc data source list");
96 }
97
98 dslist->name = strdup( cmd->data.list[0] );
99
100 /* Set data source step (avg polling interval). Default is 15s.
101 * Be careful of the case where the source is an ip address,
102 * in which case endptr = '.'
103 */
104 i=1;
105 step=strtoul(cmd->data.list[i], &endptr, 10);
106 if (step && *endptr == '\0')
107 {
108 dslist->step = step;
109 i++;
110 }
111 else
112 dslist->step = 15;
113
114 debug_msg("Polling interval for %s is %u sec.", dslist->name, dslist->step);
115 c->shortest_step = dslist->step;
116
117 dslist->sources = (g_inet_addr **) malloc( (cmd->arg_count-i) * sizeof(g_inet_addr *) );
118 if (! dslist->sources )
119 err_quit("Unable to malloc sources array");
120
121 dslist->num_sources = 0;
122 dslist->last_good_index = -1;
123
124 for ( ; i< cmd->arg_count; i++)
125 {
126 str = cmd->data.list[i];
127
128 p = strchr( str, ':' );
129 if( p )
130 {
131 /* Port is specified */
132 *p = '\0';
133 port = atoi ( p+1 );
134 }
135 else
136 port = 8649;
137
138 rv = g_gethostbyname( cmd->data.list[i], &sa, NULL);
139 if (!rv) {
140 err_msg("Warning: we failed to resolve data source name %s", cmd->data.list[i]);
141 continue;
142 }
143 str = (char*) malloc(GANGLIA_HOSTNAME_LEN);
144 my_inet_ntop(AF_INET, &sa.sin_addr, str, GANGLIA_HOSTNAME_LEN);
145
146 debug_msg("Trying to connect to %s:%d for [%s]", str, port, dslist->name);
147 dslist->sources[dslist->num_sources] = (g_inet_addr *) g_inetaddr_new ( str, port );
148 if(! dslist->sources[dslist->num_sources])
149 err_quit("Unable to create inetaddr [%s:%d] and save it to [%s]", str, port, dslist->name);
150 else
151 dslist->num_sources++;
152 free(str);
153 }
154
155 key.data = cmd->data.list[0];
156 key.size = strlen(key.data) + 1;
157
158 val.data = &dslist;
159 val.size = sizeof(dslist);
160
161 find = hash_insert( &key, &val, sources );
162 if(!find)
163 err_quit("Unable to insert list pointer into source hash\n");
164
165 debug_msg("Data inserted for [%s] into sources hash", (const char *) key.data);
166 return NULL;
167 }
168
DOTCONF_CB(cb_debug_level)169 static DOTCONF_CB(cb_debug_level)
170 {
171 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
172 c->debug_level = cmd->data.value;
173 debug_msg("Setting the debug level to %ld", cmd->data.value);
174 return NULL;
175 }
176
DOTCONF_CB(cb_xml_port)177 static DOTCONF_CB(cb_xml_port)
178 {
179 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
180 debug_msg("Setting xml port to %ld", cmd->data.value);
181 c->xml_port = cmd->data.value;
182 return NULL;
183 }
184
DOTCONF_CB(cb_interactive_port)185 static DOTCONF_CB(cb_interactive_port)
186 {
187 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
188 debug_msg("Setting interactive port to %ld", cmd->data.value);
189 c->interactive_port = cmd->data.value;
190 return NULL;
191 }
192
DOTCONF_CB(cb_server_threads)193 static DOTCONF_CB(cb_server_threads)
194 {
195 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
196 debug_msg("Setting number of xml server threads to %ld", cmd->data.value);
197 c->server_threads = cmd->data.value;
198 return NULL;
199 }
200
DOTCONF_CB(cb_umask)201 static DOTCONF_CB(cb_umask)
202 {
203 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
204 debug_msg("Setting umask to %.5lo & 07077", cmd->data.value);
205 c->umask = cmd->data.value & 07077; /* protect owner permissions */
206 return NULL;
207 }
208
DOTCONF_CB(cb_rrd_rootdir)209 static DOTCONF_CB(cb_rrd_rootdir)
210 {
211 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
212 debug_msg("Setting the RRD Rootdir to %s", cmd->data.str);
213 c->rrd_rootdir = strdup (cmd->data.str);
214 return NULL;
215 }
216
DOTCONF_CB(cb_setuid_username)217 static DOTCONF_CB(cb_setuid_username)
218 {
219 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
220 debug_msg("Setting setuid username to %s", cmd->data.str);
221 c->setuid_username = strdup(cmd->data.str);
222 return NULL;
223 }
224
DOTCONF_CB(cb_setuid)225 static DOTCONF_CB(cb_setuid)
226 {
227 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
228 c->should_setuid = cmd->data.value;
229 return NULL;
230 }
231
DOTCONF_CB(cb_scalable)232 static DOTCONF_CB(cb_scalable)
233 {
234 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
235 debug_msg("Setting scalable = %s", cmd->data.str);
236 if (!strcmp(cmd->data.str, "off"))
237 c->scalable_mode = 0;
238 return NULL;
239 }
240
DOTCONF_CB(cb_write_rrds)241 static DOTCONF_CB(cb_write_rrds)
242 {
243 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
244 debug_msg("Setting write_rrds = %s", cmd->data.str);
245 if (!strcmp(cmd->data.str, "off"))
246 c->write_rrds = cmd->data.value;
247 return NULL;
248 }
249
DOTCONF_CB(cb_case_sensitive_hostnames)250 static DOTCONF_CB(cb_case_sensitive_hostnames)
251 {
252 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
253 c->case_sensitive_hostnames = cmd->data.value;
254 return NULL;
255 }
256
DOTCONF_CB(cb_carbon_server)257 static DOTCONF_CB(cb_carbon_server)
258 {
259 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
260 debug_msg("Enabling Graphite proxy to %s", cmd->data.str);
261 c->carbon_server = strdup (cmd->data.str);
262 return NULL;
263 }
264
DOTCONF_CB(cb_carbon_port)265 static DOTCONF_CB(cb_carbon_port)
266 {
267 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
268 debug_msg("Setting carbon port to %ld", cmd->data.value);
269 c->carbon_port = cmd->data.value;
270 return NULL;
271 }
272
DOTCONF_CB(cb_carbon_protocol)273 static DOTCONF_CB(cb_carbon_protocol)
274 {
275 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
276 debug_msg("Setting carbon protocol to %s", cmd->data.str);
277 c->carbon_protocol = strdup (cmd->data.str);
278 return NULL;
279 }
280
DOTCONF_CB(cb_carbon_timeout)281 static DOTCONF_CB(cb_carbon_timeout)
282 {
283 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
284 debug_msg("Setting carbon timeout to %ld", cmd->data.value);
285 c->carbon_timeout = cmd->data.value;
286 return NULL;
287 }
288
DOTCONF_CB(cb_memcached_parameters)289 static DOTCONF_CB(cb_memcached_parameters)
290 {
291 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
292 debug_msg("Enabling memcached parameters to %s", cmd->data.str);
293 c->memcached_parameters = strdup (cmd->data.str);
294 return NULL;
295 }
296
DOTCONF_CB(cb_memcached_include_cluster_in_key)297 static DOTCONF_CB(cb_memcached_include_cluster_in_key)
298 {
299 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
300 debug_msg("Setting memcached_include_cluster_in_key to %ld", cmd->data.value);
301 c->memcached_include_cluster_in_key = cmd->data.value;
302 return NULL;
303 }
304
DOTCONF_CB(cb_graphite_prefix)305 static DOTCONF_CB(cb_graphite_prefix)
306 {
307 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
308 debug_msg("Enabling Graphite proxy to %s", cmd->data.str);
309 c->graphite_prefix = strdup (cmd->data.str);
310 return NULL;
311 }
312
DOTCONF_CB(cb_graphite_path)313 static DOTCONF_CB(cb_graphite_path)
314 {
315 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
316 debug_msg("Setting Graphite path to %s", cmd->data.str);
317 c->graphite_path = strdup (cmd->data.str);
318 return NULL;
319 }
320
DOTCONF_CB(cb_riemann_server)321 static DOTCONF_CB(cb_riemann_server)
322 {
323 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
324 debug_msg("Enabling Riemann forwarding to %s", cmd->data.str);
325 c->riemann_server = strdup (cmd->data.str);
326 return NULL;
327 }
328
DOTCONF_CB(cb_riemann_port)329 static DOTCONF_CB(cb_riemann_port)
330 {
331 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
332 debug_msg("Setting Riemann port to %ld", cmd->data.value);
333 c->riemann_port = cmd->data.value;
334 return NULL;
335 }
336
DOTCONF_CB(cb_riemann_protocol)337 static DOTCONF_CB(cb_riemann_protocol)
338 {
339 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
340 debug_msg("Setting Riemann protocol to %s", cmd->data.str);
341 c->riemann_protocol = strdup (cmd->data.str);
342 return NULL;
343 }
344
DOTCONF_CB(cb_riemann_attributes)345 static DOTCONF_CB(cb_riemann_attributes)
346 {
347 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
348 debug_msg("Riemann key-value attributes %s", cmd->data.str);
349 c->riemann_attributes = strdup (cmd->data.str);
350 return NULL;
351 }
352
DOTCONF_CB(cb_unsummarized_metrics)353 static DOTCONF_CB(cb_unsummarized_metrics)
354 {
355 int i;
356 llist_entry *le;
357 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
358
359 for (i = 0; i < cmd->arg_count; i++)
360 {
361 le = (llist_entry *)malloc(sizeof(llist_entry));
362 le->val = strdup(cmd->data.list[i]);
363 llist_add(&(c->unsummarized_metrics), le);
364 debug_msg("Adding %s to unsummarized_metrics", (const char *) le->val);
365 }
366 return NULL;
367 }
368
DOTCONF_CB(cb_unsummarized_sflow_vm_metrics)369 static DOTCONF_CB(cb_unsummarized_sflow_vm_metrics)
370 {
371 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
372 debug_msg("Setting unsummarized_sflow_vm_metrics = %ld", cmd->data.value);
373 c->unsummarized_sflow_vm_metrics = cmd->data.value;
374 return NULL;
375 }
376
DOTCONF_CB(cb_summarized_metrics)377 static DOTCONF_CB(cb_summarized_metrics)
378 {
379 int i;
380 llist_entry *le;
381 gmetad_config_t *c = cmd->option->info;
382
383 for (i = 0; i < cmd->arg_count; i++)
384 {
385 le = malloc(sizeof(*le));
386 le->val = strdup(cmd->data.list[i]);
387 llist_add(&(c->summarized_metrics), le);
388 debug_msg("Adding %s to summarized_metrics", (const char *)le->val);
389 }
390 return NULL;
391 }
392
DOTCONF_CB(cb_rrdcached_address)393 static DOTCONF_CB(cb_rrdcached_address)
394 {
395 gmetad_config_t *c = (gmetad_config_t*) cmd->option->info;
396 char *ip, *tmp, *f;
397 long port;
398
399 f = tmp = strdup(cmd->data.str);
400 if ((ip = strsep(&tmp, ":")) == NULL ||
401 inet_pton(AF_INET, ip, &c->rrdcached_address.sin_addr) != 1)
402 {
403 err_quit("Expected IPv4 address in form a.b.c.d:port for "
404 "rrdcached_address, got %s\n", cmd->data.str);
405 }
406 port = strtol(tmp, NULL, 10);
407 if ((port == 0 && errno == EINVAL) ||
408 ((port == LONG_MIN || port == LONG_MAX) && errno == ERANGE) ||
409 port < 0 || port > 65535)
410 {
411 err_quit("Expected IPv4 port within range; got %s\n", tmp);
412 }
413
414 c->rrdcached_address.sin_family = AF_INET;
415 c->rrdcached_address.sin_port = htons(port);
416 c->rrdcached_addrstr = strdup(cmd->data.str);
417 free(f);
418
419 return NULL;
420 }
421
FUNC_ERRORHANDLER(errorhandler)422 static FUNC_ERRORHANDLER(errorhandler)
423 {
424 err_quit("gmetad config file error: %s\n", msg);
425 return 0;
426 }
427
428 static configoption_t gmetad_options[] =
429 {
430 {"data_source", ARG_LIST, cb_data_source, &gmetad_config, 0},
431 {"gridname", ARG_STR, cb_gridname, &gmetad_config, 0},
432 {"authority", ARG_STR, cb_authority, &gmetad_config, 0},
433 {"trusted_hosts", ARG_LIST, cb_trusted_hosts, &gmetad_config, 0},
434 {"all_trusted", ARG_INT, cb_all_trusted, &gmetad_config, 0},
435 {"debug_level", ARG_INT, cb_debug_level, &gmetad_config, 0},
436 {"xml_port", ARG_INT, cb_xml_port, &gmetad_config, 0},
437 {"interactive_port", ARG_INT, cb_interactive_port, &gmetad_config, 0},
438 {"server_threads", ARG_INT, cb_server_threads, &gmetad_config, 0},
439 {"umask", ARG_INT, cb_umask, &gmetad_config, 0},
440 {"rrd_rootdir", ARG_STR, cb_rrd_rootdir, &gmetad_config, 0},
441 {"rrdcached_address", ARG_STR, cb_rrdcached_address, &gmetad_config, 0},
442 {"setuid", ARG_TOGGLE, cb_setuid, &gmetad_config, 0},
443 {"setuid_username", ARG_STR, cb_setuid_username, &gmetad_config, 0},
444 {"scalable", ARG_STR, cb_scalable, &gmetad_config, 0},
445 {"write_rrds", ARG_STR, cb_write_rrds, &gmetad_config, 0},
446 {"RRAs", ARG_LIST, cb_RRAs, &gmetad_config, 0},
447 {"case_sensitive_hostnames", ARG_INT, cb_case_sensitive_hostnames, &gmetad_config, 0},
448 {"carbon_server", ARG_STR, cb_carbon_server, &gmetad_config, 0},
449 {"carbon_port", ARG_INT, cb_carbon_port, &gmetad_config, 0},
450 {"carbon_protocol", ARG_STR, cb_carbon_protocol, &gmetad_config, 0},
451 {"carbon_timeout", ARG_INT, cb_carbon_timeout, &gmetad_config, 0},
452 {"memcached_parameters", ARG_STR, cb_memcached_parameters, &gmetad_config, 0},
453 {"memcached_include_cluster_in_key", ARG_INT, cb_memcached_include_cluster_in_key, &gmetad_config, 0},
454 {"graphite_prefix", ARG_STR, cb_graphite_prefix, &gmetad_config, 0},
455 {"graphite_path", ARG_STR, cb_graphite_path, &gmetad_config, 0},
456 {"riemann_server", ARG_STR, cb_riemann_server, &gmetad_config, 0},
457 {"riemann_port", ARG_INT, cb_riemann_port, &gmetad_config, 0},
458 {"riemann_protocol", ARG_STR, cb_riemann_protocol, &gmetad_config, 0},
459 {"riemann_attributes", ARG_STR, cb_riemann_attributes, &gmetad_config, 0},
460 {"unsummarized_metrics", ARG_LIST, cb_unsummarized_metrics, &gmetad_config, 0},
461 {"unsummarized_sflow_vm_metrics", ARG_TOGGLE, cb_unsummarized_sflow_vm_metrics, &gmetad_config, 0},
462 {"summarized_metrics", ARG_LIST, cb_summarized_metrics, &gmetad_config, 0},
463 LAST_OPTION
464 };
465
466 static void
set_defaults(gmetad_config_t * config)467 set_defaults (gmetad_config_t *config)
468 {
469 /* Gmetad defaults */
470 config->gridname = "unspecified";
471 config->xml_port = 8651;
472 config->interactive_port = 8652;
473 config->server_threads = 4;
474 config->umask = 0;
475 config->trusted_hosts = NULL;
476 config->debug_level = 0;
477 config->should_setuid = 1;
478 config->setuid_username = "nobody";
479 config->rrd_rootdir = "/var/lib/ganglia/rrds";
480 config->rrdcached_addrstr = NULL;
481 memset(&config->rrdcached_address, 0, sizeof (config->rrdcached_address));
482 config->write_rrds = 1;
483 config->scalable_mode = 1;
484 config->all_trusted = 0;
485 config->num_RRAs = 3;
486 config->RRAs[0] = "RRA:AVERAGE:0.5:1:5856";
487 config->RRAs[1] = "RRA:AVERAGE:0.5:4:20160";
488 config->RRAs[2] = "RRA:AVERAGE:0.5:40:52704";
489 config->case_sensitive_hostnames = 1;
490 config->carbon_port = 2003;
491 config->carbon_protocol = "tcp";
492 config->carbon_timeout = 500;
493 config->memcached_include_cluster_in_key = 0;
494 config->riemann_port = 5555;
495 config->riemann_protocol = "udp";
496 config->riemann_attributes = NULL;
497 config->unsummarized_metrics = NULL;
498 config->unsummarized_sflow_vm_metrics = 0;
499 config->summarized_metrics = NULL;
500 }
501
502 int
parse_config_file(char * config_file)503 parse_config_file ( char *config_file )
504 {
505 configfile_t *configfile;
506
507 set_defaults(&gmetad_config);
508
509 configfile = dotconf_create( config_file, gmetad_options, 0, CASE_INSENSITIVE );
510 if (!configfile)
511 {
512 err_quit("Unable to open config file: %s\n", config_file);
513 }
514
515 configfile->errorhandler = (dotconf_errorhandler_t) errorhandler;
516
517 if (dotconf_command_loop(configfile) == 0)
518 {
519 dotconf_cleanup(configfile);
520 err_quit("dotconf_command_loop error");
521 }
522 return 0;
523 }
524
525 int
number_of_datasources(char * config_file)526 number_of_datasources ( char *config_file )
527 {
528 int number_of_sources = 0;
529 char buf[1024];
530 configfile_t *configfile;
531
532 configfile = dotconf_create( config_file, gmetad_options, 0, CASE_INSENSITIVE );
533 if (!configfile) {
534 err_quit("Unable to open config file: %s\n", config_file);
535 }
536
537 while (! dotconf_get_next_line( buf, 1024, configfile ))
538 {
539 if( strstr( buf, "data_source" ) && (buf[0] != '#') )
540 {
541 number_of_sources++;
542 }
543 }
544 dotconf_cleanup(configfile);
545 return number_of_sources;
546 }
547
548