This source file includes following definitions.
- cib_notify_send_one
- cib_notify_send
- attach_cib_generation
- cib_diff_notify
- cib_replace_notify
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <inttypes.h>
17
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <fcntl.h>
21
22 #include <time.h>
23
24 #include <crm/crm.h>
25 #include <crm/cib/internal.h>
26 #include <crm/msg_xml.h>
27
28 #include <crm/common/xml.h>
29 #include <crm/common/remote_internal.h>
30 #include <pacemaker-based.h>
31
32 struct cib_notification_s {
33 xmlNode *msg;
34 struct iovec *iov;
35 int32_t iov_size;
36 };
37
38 static void
39 cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
40 {
41 const char *type = NULL;
42 gboolean do_send = FALSE;
43 int rc = pcmk_rc_ok;
44
45 pcmk__client_t *client = value;
46 struct cib_notification_s *update = user_data;
47
48 if (client->ipcs == NULL && client->remote == NULL) {
49 crm_warn("Skipping client with NULL channel");
50 return;
51 }
52
53 type = crm_element_value(update->msg, F_SUBTYPE);
54 CRM_LOG_ASSERT(type != NULL);
55
56 if (pcmk_is_set(client->flags, cib_notify_diff)
57 && pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
58
59 do_send = TRUE;
60
61 } else if (pcmk_is_set(client->flags, cib_notify_replace)
62 && pcmk__str_eq(type, T_CIB_REPLACE_NOTIFY, pcmk__str_casei)) {
63 do_send = TRUE;
64
65 } else if (pcmk_is_set(client->flags, cib_notify_confirm)
66 && pcmk__str_eq(type, T_CIB_UPDATE_CONFIRM, pcmk__str_casei)) {
67 do_send = TRUE;
68
69 } else if (pcmk_is_set(client->flags, cib_notify_pre)
70 && pcmk__str_eq(type, T_CIB_PRE_NOTIFY, pcmk__str_casei)) {
71 do_send = TRUE;
72
73 } else if (pcmk_is_set(client->flags, cib_notify_post)
74 && pcmk__str_eq(type, T_CIB_POST_NOTIFY, pcmk__str_casei)) {
75
76 do_send = TRUE;
77 }
78
79 if (do_send) {
80 switch (PCMK__CLIENT_TYPE(client)) {
81 case pcmk__client_ipc:
82 rc = pcmk__ipc_send_iov(client, update->iov,
83 crm_ipc_server_event);
84 if (rc != pcmk_rc_ok) {
85 crm_warn("Could not notify client %s: %s " CRM_XS " id=%s",
86 pcmk__client_name(client), pcmk_rc_str(rc),
87 client->id);
88 }
89 break;
90 #ifdef HAVE_GNUTLS_GNUTLS_H
91 case pcmk__client_tls:
92 #endif
93 case pcmk__client_tcp:
94 crm_debug("Sent %s notification to client %s (id %s)",
95 type, pcmk__client_name(client), client->id);
96 pcmk__remote_send_xml(client->remote, update->msg);
97 break;
98 default:
99 crm_err("Unknown transport for client %s "
100 CRM_XS " flags=%#016" PRIx64,
101 pcmk__client_name(client), client->flags);
102 }
103 }
104 }
105
106 static void
107 cib_notify_send(xmlNode * xml)
108 {
109 struct iovec *iov;
110 struct cib_notification_s update;
111
112 ssize_t bytes = 0;
113 int rc = pcmk__ipc_prepare_iov(0, xml, 0, &iov, &bytes);
114
115 if (rc == pcmk_rc_ok) {
116 update.msg = xml;
117 update.iov = iov;
118 update.iov_size = bytes;
119 pcmk__foreach_ipc_client(cib_notify_send_one, &update);
120
121 } else {
122 crm_notice("Could not notify clients: %s " CRM_XS " rc=%d",
123 pcmk_rc_str(rc), rc);
124 }
125 pcmk_free_ipc_event(iov);
126 }
127
128 static void
129 attach_cib_generation(xmlNode *msg, const char *field, xmlNode *a_cib)
130 {
131 xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
132
133 if (a_cib != NULL) {
134 copy_in_properties(generation, a_cib);
135 }
136 add_message_xml(msg, field, generation);
137 free_xml(generation);
138 }
139
140 void
141 cib_diff_notify(const char *op, int result, const char *call_id,
142 const char *client_id, const char *client_name,
143 const char *origin, xmlNode *update, xmlNode *diff)
144 {
145 int add_updates = 0;
146 int add_epoch = 0;
147 int add_admin_epoch = 0;
148
149 int del_updates = 0;
150 int del_epoch = 0;
151 int del_admin_epoch = 0;
152
153 uint8_t log_level = LOG_TRACE;
154
155 xmlNode *update_msg = NULL;
156 const char *type = NULL;
157
158 if (diff == NULL) {
159 return;
160 }
161
162 if (result != pcmk_ok) {
163 log_level = LOG_WARNING;
164 }
165
166 cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
167 &del_admin_epoch, &del_epoch, &del_updates);
168
169 if ((add_admin_epoch != del_admin_epoch)
170 || (add_epoch != del_epoch)
171 || (add_updates != del_updates)) {
172
173 do_crm_log(log_level,
174 "Updated CIB generation %d.%d.%d to %d.%d.%d from client "
175 "%s%s%s (%s) (%s)",
176 del_admin_epoch, del_epoch, del_updates,
177 add_admin_epoch, add_epoch, add_updates,
178 client_name,
179 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
180 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
181
182 } else if ((add_admin_epoch != 0)
183 || (add_epoch != 0)
184 || (add_updates != 0)) {
185
186 do_crm_log(log_level,
187 "Local-only change to CIB generation %d.%d.%d from client "
188 "%s%s%s (%s) (%s)",
189 add_admin_epoch, add_epoch, add_updates,
190 client_name,
191 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
192 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
193 }
194
195 update_msg = create_xml_node(NULL, "notify");
196
197 crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
198 crm_xml_add(update_msg, F_SUBTYPE, T_CIB_DIFF_NOTIFY);
199 crm_xml_add(update_msg, F_CIB_OPERATION, op);
200 crm_xml_add(update_msg, F_CIB_CLIENTID, client_id);
201 crm_xml_add(update_msg, F_CIB_CALLID, call_id);
202 crm_xml_add(update_msg, F_ORIG, origin);
203 crm_xml_add_int(update_msg, F_CIB_RC, result);
204
205 if (update != NULL) {
206 type = crm_element_name(update);
207 crm_trace("Setting type to update->name: %s", type);
208 } else {
209 type = crm_element_name(diff);
210 crm_trace("Setting type to new_obj->name: %s", type);
211 }
212 crm_xml_add(update_msg, F_CIB_OBJID, ID(diff));
213 crm_xml_add(update_msg, F_CIB_OBJTYPE, type);
214 attach_cib_generation(update_msg, "cib_generation", the_cib);
215
216 if (update != NULL) {
217 add_message_xml(update_msg, F_CIB_UPDATE, update);
218 }
219 add_message_xml(update_msg, F_CIB_UPDATE_RESULT, diff);
220
221 cib_notify_send(update_msg);
222 free_xml(update_msg);
223 }
224
225 void
226 cib_replace_notify(const char *op, int result, const char *call_id,
227 const char *client_id, const char *client_name,
228 const char *origin, xmlNode *update, xmlNode *diff,
229 uint32_t change_section)
230 {
231 xmlNode *replace_msg = NULL;
232
233 int add_updates = 0;
234 int add_epoch = 0;
235 int add_admin_epoch = 0;
236
237 int del_updates = 0;
238 int del_epoch = 0;
239 int del_admin_epoch = 0;
240
241 uint8_t log_level = LOG_INFO;
242
243 if (diff == NULL) {
244 return;
245 }
246
247 if (result != pcmk_ok) {
248 log_level = LOG_WARNING;
249 }
250
251 cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
252 &del_admin_epoch, &del_epoch, &del_updates);
253
254 if (del_updates < 0) {
255 crm_log_xml_debug(diff, "Bad replace diff");
256 }
257
258 if ((add_admin_epoch != del_admin_epoch)
259 || (add_epoch != del_epoch)
260 || (add_updates != del_updates)) {
261
262 do_crm_log(log_level,
263 "Replaced CIB generation %d.%d.%d with %d.%d.%d from client "
264 "%s%s%s (%s) (%s)",
265 del_admin_epoch, del_epoch, del_updates,
266 add_admin_epoch, add_epoch, add_updates,
267 client_name,
268 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
269 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
270
271 } else if ((add_admin_epoch != 0)
272 || (add_epoch != 0)
273 || (add_updates != 0)) {
274
275 do_crm_log(log_level,
276 "Local-only replace of CIB generation %d.%d.%d from client "
277 "%s%s%s (%s) (%s)",
278 add_admin_epoch, add_epoch, add_updates,
279 client_name,
280 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
281 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
282 }
283
284 replace_msg = create_xml_node(NULL, "notify-replace");
285
286 crm_xml_add(replace_msg, F_TYPE, T_CIB_NOTIFY);
287 crm_xml_add(replace_msg, F_SUBTYPE, T_CIB_REPLACE_NOTIFY);
288 crm_xml_add(replace_msg, F_CIB_OPERATION, op);
289 crm_xml_add(replace_msg, F_CIB_CLIENTID, client_id);
290 crm_xml_add(replace_msg, F_CIB_CALLID, call_id);
291 crm_xml_add(replace_msg, F_ORIG, origin);
292 crm_xml_add_int(replace_msg, F_CIB_RC, result);
293 crm_xml_add_ll(replace_msg, F_CIB_CHANGE_SECTION,
294 (long long) change_section);
295 attach_cib_generation(replace_msg, "cib-replace-generation", update);
296
297
298
299
300
301 crm_log_xml_trace(replace_msg, "CIB replaced");
302
303 cib_notify_send(replace_msg);
304 free_xml(replace_msg);
305 }