blob: 206246c65b6ab7a765490aa7fc90647395ae9735 [file] [log] [blame]
Harald Welte1a36f332018-06-04 17:36:33 +02001/* Simple Osmocom System Monitor (osysmon) */
2
3/* (C) 2018 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301, USA.
22 */
23
24#include <unistd.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <signal.h>
Pau Espin Pedrolae253992018-12-12 19:37:02 +010029#include <getopt.h>
Harald Welte1a36f332018-06-04 17:36:33 +020030
Harald Welte54ca6f42018-06-04 21:52:30 +020031#include "config.h"
Harald Welte1a36f332018-06-04 17:36:33 +020032#include "osysmon.h"
33#include "value_node.h"
34
35#include <osmocom/core/msgb.h>
36#include <osmocom/core/logging.h>
37#include <osmocom/core/application.h>
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +010038#include <osmocom/core/timer.h>
Harald Welte1a36f332018-06-04 17:36:33 +020039
40static struct log_info log_info = {};
41
42static int osysmon_go_parent(struct vty *vty)
43{
44 switch (vty->node) {
45 case CTRL_CLIENT_NODE:
46 case CTRL_CLIENT_GETVAR_NODE:
47 return osysmon_ctrl_go_parent(vty);
48 }
49 return vty->node;
50}
51
52static int osysmon_is_config_node(struct vty *vty, int node)
53{
54 switch (node) {
55 /* no non-config-nodes */
56 default:
57 return 1;
58 }
59}
60
61
62static struct vty_app_info vty_info = {
63 .name = "osysmon",
64 .copyright =
65 "Copyright (C) 2008-2018 Harald Welte\r\n"
66 "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\r\n"
67 "This is free software: you are free to change and redistribute it.\r\n"
68 "There is NO WARRANTY, to the extent permitted by law.\r\n",
Harald Welte54ca6f42018-06-04 21:52:30 +020069 .version = PACKAGE_VERSION,
Harald Welte1a36f332018-06-04 17:36:33 +020070 .go_parent_cb = osysmon_go_parent,
71 .is_config_node = osysmon_is_config_node,
72};
73
Harald Welte1a36f332018-06-04 17:36:33 +020074struct osysmon_state *g_oss;
75
76
Harald Welte3dada482018-06-04 18:22:03 +020077static void print_node(struct value_node *node, unsigned int indent)
Harald Welte1a36f332018-06-04 17:36:33 +020078{
Harald Welte3dada482018-06-04 18:22:03 +020079 unsigned int i;
80
Harald Welte1a36f332018-06-04 17:36:33 +020081 if (node->value) {
Harald Welte3dada482018-06-04 18:22:03 +020082 for (i = 0; i < indent; i++)
83 fputc(' ', stdout);
Harald Welte1a36f332018-06-04 17:36:33 +020084 printf("%s: %s\n", node->name, node->value);
85 } else {
86 struct value_node *vn;
Harald Welte3dada482018-06-04 18:22:03 +020087 for (i = 0; i < indent; i++)
88 fputc(' ', stdout);
89 printf("%s\n", node->name);
Harald Welte1a36f332018-06-04 17:36:33 +020090 llist_for_each_entry(vn, &node->children, list)
Harald Welte3dada482018-06-04 18:22:03 +020091 print_node(vn, indent+2);
Harald Welte1a36f332018-06-04 17:36:33 +020092 }
93}
94
95static void display_update(struct value_node *root)
96{
Harald Welte3dada482018-06-04 18:22:03 +020097 print_node(root, 0);
Harald Welte1a36f332018-06-04 17:36:33 +020098}
99
100static void signal_handler(int signal)
101{
102 fprintf(stderr, "Signal %u received", signal);
103
104 switch(signal) {
105 case SIGUSR1:
106 talloc_report(g_oss, stderr);
107 break;
108 default:
109 break;
110 }
111}
112
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100113static void print_usage()
114{
115 printf("Usage: osmo-sysmon\n");
116}
117
118static void print_help()
119{
120 printf(" -h --help This text.\n");
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100121 printf(" -o --oneshot Oneshot mode. Execute queries once, then exit.\n");
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100122 printf(" -c --config-file filename The config file to use.\n");
123 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM Enable debugging.\n");
124 printf(" -D --daemonize Fork the process into a background daemon.\n");
125 printf(" -s --disable-color Do not print ANSI colors in the log\n");
126 printf(" -T --timestamp Prefix every log line with a timestamp.\n");
127 printf(" -e --log-level number Set a global loglevel.\n");
Oliver Smith433f7052019-02-22 10:40:08 +0100128 printf(" -V --version Print the version of osmo-sysmon.\n");
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100129}
130
131static struct {
132 const char *config_file;
133 bool daemonize;
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100134 bool oneshot;
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100135} cmdline_opts = {
136 .config_file = "osmo-sysmon.cfg",
137 .daemonize = false,
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100138 .oneshot = false,
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100139};
140
141static void handle_options(int argc, char **argv)
142{
143 while (1) {
144 int option_index = 0, c;
145 static struct option long_options[] = {
146 {"help", 0, 0, 'h'},
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100147 {"oneshot", 0, 0, 'o'},
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100148 {"config-file", 1, 0, 'c'},
149 {"debug", 1, 0, 'd'},
150 {"daemonize", 0, 0, 'D'},
151 {"disable-color", 0, 0, 's'},
152 {"log-level", 1, 0, 'e'},
153 {"timestamp", 0, 0, 'T'},
154 {"version", 0, 0, 'V' },
155 {0, 0, 0, 0}
156 };
157
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100158 c = getopt_long(argc, argv, "hoc:d:Dse:TV",
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100159 long_options, &option_index);
160 if (c == -1)
161 break;
162
163 switch (c) {
164 case 'h':
165 print_usage();
166 print_help();
167 exit(0);
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100168 case 'o':
169 cmdline_opts.oneshot = true;
170 break;
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100171 case 'c':
172 cmdline_opts.config_file = optarg;
173 break;
174 case 'd':
175 log_parse_category_mask(osmo_stderr_target, optarg);
176 break;
177 case 'D':
178 cmdline_opts.daemonize = 1;
179 break;
180 case 's':
181 log_set_use_color(osmo_stderr_target, 0);
182 break;
183 case 'e':
184 log_set_log_level(osmo_stderr_target, atoi(optarg));
185 break;
186 case 'T':
187 log_set_print_timestamp(osmo_stderr_target, 1);
188 break;
189 case 'V':
190 print_version(1);
191 exit(0);
192 break;
193 default:
194 /* catch unknown options *as well as* missing arguments. */
195 fprintf(stderr, "Error in command line options. Exiting.\n");
196 exit(-1);
197 break;
198 }
199 }
Harald Welte8984bea2019-12-03 22:29:26 +0100200
201 if (argc > optind) {
202 fprintf(stderr, "Unsupported positional arguments on command line\n");
203 exit(2);
204 }
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100205}
206
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100207static struct osmo_timer_list print_timer;
208int ping_init;
209
210static void print_nodes(__attribute__((unused)) void *data)
211{
212 struct value_node *root = value_node_add(NULL, "root", NULL);
213 osysmon_openvpn_poll(root);
214 osysmon_sysinfo_poll(root);
215 osysmon_ctrl_poll(root);
216 osysmon_rtnl_poll(root);
217
218 if (ping_init == 0)
219 osysmon_ping_poll(root);
220
221 osysmon_file_poll(root);
Pau Espin Pedrol92016772019-03-18 17:24:34 +0100222 osysmon_shellcmd_poll(root);
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100223
224 display_update(root);
225 value_node_del(root);
226
Daniel Willmannebbfbbd2019-11-07 17:04:23 +0100227 if (cmdline_opts.oneshot)
228 exit(0);
229
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100230 osmo_timer_schedule(&print_timer, 1, 0);
231}
232
Harald Welte1a36f332018-06-04 17:36:33 +0200233int main(int argc, char **argv)
234{
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100235 int rc;
Harald Welte1a36f332018-06-04 17:36:33 +0200236
237 osmo_init_logging2(NULL, &log_info);
238
239 g_oss = talloc_zero(NULL, struct osysmon_state);
Pau Espin Pedrol92016772019-03-18 17:24:34 +0100240 INIT_LLIST_HEAD(&g_oss->shellcmds);
Harald Welte1a36f332018-06-04 17:36:33 +0200241 INIT_LLIST_HEAD(&g_oss->ctrl_clients);
Max9a852f22019-01-31 15:58:57 +0100242 INIT_LLIST_HEAD(&g_oss->openvpn_clients);
Harald Welte9e7fe002018-06-04 20:09:26 +0200243 INIT_LLIST_HEAD(&g_oss->netdevs);
Harald Welte81e20232018-06-04 21:25:56 +0200244 INIT_LLIST_HEAD(&g_oss->files);
Harald Welte1a36f332018-06-04 17:36:33 +0200245
246 vty_init(&vty_info);
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100247 handle_options(argc, argv);
Harald Welte32f7a992018-06-04 18:07:33 +0200248 osysmon_sysinfo_init();
Pau Espin Pedrol92016772019-03-18 17:24:34 +0100249 osysmon_shellcmd_init();
Harald Welte1a36f332018-06-04 17:36:33 +0200250 osysmon_ctrl_init();
Max9a852f22019-01-31 15:58:57 +0100251 osysmon_openvpn_init();
Harald Welte9e7fe002018-06-04 20:09:26 +0200252 osysmon_rtnl_init();
Max8066a412019-01-28 23:59:03 +0100253 ping_init = osysmon_ping_init();
Harald Welte81e20232018-06-04 21:25:56 +0200254 osysmon_file_init();
Harald Welte1a36f332018-06-04 17:36:33 +0200255
Maxada0d1a2019-01-30 16:31:45 +0100256 signal(SIGUSR1, &signal_handler);
257 signal(SIGUSR2, &signal_handler);
258 osmo_init_ignore_signals();
259
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100260 rc = vty_read_config_file(cmdline_opts.config_file, NULL);
Harald Welte1a36f332018-06-04 17:36:33 +0200261 if (rc < 0) {
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100262 fprintf(stderr, "Failed to parse the config file %s\n",
263 cmdline_opts.config_file);
Harald Welte1a36f332018-06-04 17:36:33 +0200264 exit(2);
265 }
266
Pau Espin Pedrolae253992018-12-12 19:37:02 +0100267 if (cmdline_opts.daemonize) {
268 rc = osmo_daemonize();
269 if (rc < 0) {
270 perror("Error during daemonize");
271 exit(1);
272 }
273 }
274
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100275 osmo_timer_setup(&print_timer, print_nodes, NULL);
276 osmo_timer_schedule(&print_timer, 0, 0);
Max8066a412019-01-28 23:59:03 +0100277
Pau Espin Pedrol69d80b72019-03-15 18:34:36 +0100278 while (1)
Max9a852f22019-01-31 15:58:57 +0100279 osmo_select_main(0);
280
Harald Welte1a36f332018-06-04 17:36:33 +0200281 exit(0);
282}