This source file includes following definitions.
- main
- usage
- cib_connection_destroy
- cibmon_diff
- cibmon_shutdown
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13
14 #include <crm/crm.h>
15
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <fcntl.h>
23
24 #include <crm/msg_xml.h>
25 #include <crm/common/xml.h>
26 #include <crm/common/mainloop.h>
27 #include <crm/cib/internal.h>
28
29 #include <crm/common/ipc.h>
30 #include <crm/pengine/status.h>
31
32 #include <crm/cib.h>
33
34 #ifdef HAVE_GETOPT_H
35 # include <getopt.h>
36 #endif
37
38 static int max_failures = 30;
39
40 static gboolean log_diffs = FALSE;
41 static gboolean log_updates = FALSE;
42
43 static GMainLoop *mainloop = NULL;
44 void usage(const char *cmd, crm_exit_t exit_status);
45 void cib_connection_destroy(gpointer user_data);
46
47 void cibmon_shutdown(int nsig);
48 void cibmon_diff(const char *event, xmlNode * msg);
49
50 static cib_t *cib = NULL;
51 static xmlNode *cib_copy = NULL;
52
53 #define OPTARGS "V?m:du"
54
55 int
56 main(int argc, char **argv)
57 {
58 int argerr = 0;
59 int flag;
60 int attempts = 0;
61 int rc = pcmk_ok;
62
63 #ifdef HAVE_GETOPT_H
64 int option_index = 0;
65
66 static struct option long_options[] = {
67
68 {"verbose", 0, 0, 'V'},
69 {"help", 0, 0, '?'},
70 {"log-diffs", 0, 0, 'd'},
71 {"log-updates", 0, 0, 'u'},
72 {"max-conn-fail", 1, 0, 'm'},
73 {0, 0, 0, 0}
74 };
75 #endif
76
77 crm_log_cli_init("cibmon");
78
79 crm_signal_handler(SIGTERM, cibmon_shutdown);
80
81 while (1) {
82 #ifdef HAVE_GETOPT_H
83 flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index);
84 #else
85 flag = getopt(argc, argv, OPTARGS);
86 #endif
87 if (flag == -1)
88 break;
89
90 switch (flag) {
91 case 'V':
92 crm_bump_log_level(argc, argv);
93 break;
94 case '?':
95 usage(crm_system_name, CRM_EX_OK);
96 break;
97 case 'd':
98 log_diffs = TRUE;
99 break;
100 case 'u':
101 log_updates = TRUE;
102 break;
103 case 'm':
104 max_failures = crm_parse_int(optarg, "30");
105 break;
106 default:
107 printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
108 ++argerr;
109 break;
110 }
111 }
112
113 if (optind < argc) {
114 printf("non-option ARGV-elements: ");
115 while (optind < argc)
116 printf("%s ", argv[optind++]);
117 printf("\n");
118 }
119
120 if (optind > argc) {
121 ++argerr;
122 }
123
124 if (argerr) {
125 usage(crm_system_name, CRM_EX_USAGE);
126 }
127
128 cib = cib_new();
129
130 do {
131 sleep(1);
132 rc = cib->cmds->signon(cib, crm_system_name, cib_query);
133
134 } while (rc == -ENOTCONN && attempts++ < max_failures);
135
136 if (rc != pcmk_ok) {
137 crm_err("Signon to CIB failed: %s", pcmk_strerror(rc));
138 goto fail;
139 }
140
141 crm_debug("Setting dnotify");
142 rc = cib->cmds->set_connection_dnotify(cib, cib_connection_destroy);
143 if (rc != pcmk_ok) {
144 crm_err("Failed to set dnotify callback: %s", pcmk_strerror(rc));
145 goto fail;
146 }
147
148 crm_debug("Setting diff callback");
149 rc = cib->cmds->add_notify_callback(cib, T_CIB_DIFF_NOTIFY, cibmon_diff);
150 if (rc != pcmk_ok) {
151 crm_err("Failed to set diff callback: %s", pcmk_strerror(rc));
152 goto fail;
153 }
154
155 mainloop = g_main_loop_new(NULL, FALSE);
156 crm_info("Starting mainloop");
157 g_main_loop_run(mainloop);
158 crm_trace("%s exiting normally", crm_system_name);
159 fflush(stderr);
160 return CRM_EX_OK;
161
162 fail:
163 crm_err("Setup failed, could not monitor CIB actions");
164 return CRM_EX_ERROR;
165 }
166
167 void
168 usage(const char *cmd, crm_exit_t exit_status)
169 {
170 FILE *stream;
171
172 stream = (exit_status == CRM_EX_OK)? stdout : stderr;
173 fflush(stream);
174
175 crm_exit(exit_status);
176 }
177
178 void
179 cib_connection_destroy(gpointer user_data)
180 {
181 cib_t *conn = user_data;
182
183 crm_err("Connection to the CIB terminated... exiting");
184 conn->cmds->signoff(conn);
185 g_main_loop_quit(mainloop);
186 return;
187 }
188
189 void
190 cibmon_diff(const char *event, xmlNode * msg)
191 {
192 int rc = -1;
193 const char *op = NULL;
194 unsigned int log_level = LOG_INFO;
195
196 xmlNode *diff = NULL;
197 xmlNode *cib_last = NULL;
198 xmlNode *update = get_message_xml(msg, F_CIB_UPDATE);
199
200 if (msg == NULL) {
201 crm_err("NULL update");
202 return;
203 }
204
205 crm_element_value_int(msg, F_CIB_RC, &rc);
206 op = crm_element_value(msg, F_CIB_OPERATION);
207 diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);
208
209 if (rc < pcmk_ok) {
210 log_level = LOG_WARNING;
211 do_crm_log(log_level, "[%s] %s ABORTED: %s", event, op, pcmk_strerror(rc));
212 return;
213 }
214
215 if (log_diffs) {
216 xml_log_patchset(log_level, op, diff);
217 }
218
219 if (log_updates && update != NULL) {
220 crm_log_xml_trace(update, "raw_update");
221 }
222
223 if (cib_copy != NULL) {
224 cib_last = cib_copy;
225 cib_copy = NULL;
226 rc = cib_process_diff(op, cib_force_diff, NULL, NULL, diff, cib_last, &cib_copy, NULL);
227
228 if (rc != pcmk_ok) {
229 crm_debug("Update didn't apply, requesting full copy: %s", pcmk_strerror(rc));
230 free_xml(cib_copy);
231 cib_copy = NULL;
232 }
233 }
234
235 if (cib_copy == NULL) {
236 rc = cib->cmds->query(cib, NULL, &cib_copy, cib_scope_local | cib_sync_call);
237 }
238
239 if(rc == -EACCES) {
240 crm_exit(CRM_EX_INSUFFICIENT_PRIV);
241 }
242
243 free_xml(cib_last);
244 }
245
246 void
247 cibmon_shutdown(int nsig)
248 {
249 crm_exit(CRM_EX_OK);
250 }