This source file includes following definitions.
- cib_notify_send_one
- cib_notify_send
- attach_cib_generation
- cib_diff_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 <glib.h>
25 #include <libxml/tree.h>
26
27 #include <crm/crm.h>
28 #include <crm/cib/internal.h>
29 #include <crm/msg_xml.h>
30
31 #include <crm/common/xml.h>
32 #include <crm/common/remote_internal.h>
33 #include <pacemaker-based.h>
34
35 struct cib_notification_s {
36 const xmlNode *msg;
37 struct iovec *iov;
38 int32_t iov_size;
39 };
40
41 static void
42 cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
43 {
44 const char *type = NULL;
45 gboolean do_send = FALSE;
46 int rc = pcmk_rc_ok;
47
48 pcmk__client_t *client = value;
49 struct cib_notification_s *update = user_data;
50
51 if (client->ipcs == NULL && client->remote == NULL) {
52 crm_warn("Skipping client with NULL channel");
53 return;
54 }
55
56 type = crm_element_value(update->msg, F_SUBTYPE);
57 CRM_LOG_ASSERT(type != NULL);
58
59 if (pcmk_is_set(client->flags, cib_notify_diff)
60 && pcmk__str_eq(type, T_CIB_DIFF_NOTIFY, pcmk__str_casei)) {
61
62 do_send = TRUE;
63
64 } else if (pcmk_is_set(client->flags, cib_notify_confirm)
65 && pcmk__str_eq(type, T_CIB_UPDATE_CONFIRM, pcmk__str_casei)) {
66 do_send = TRUE;
67
68 } else if (pcmk_is_set(client->flags, cib_notify_pre)
69 && pcmk__str_eq(type, T_CIB_PRE_NOTIFY, pcmk__str_casei)) {
70 do_send = TRUE;
71
72 } else if (pcmk_is_set(client->flags, cib_notify_post)
73 && pcmk__str_eq(type, T_CIB_POST_NOTIFY, pcmk__str_casei)) {
74
75 do_send = TRUE;
76 }
77
78 if (do_send) {
79 switch (PCMK__CLIENT_TYPE(client)) {
80 case pcmk__client_ipc:
81 rc = pcmk__ipc_send_iov(client, update->iov,
82 crm_ipc_server_event);
83 if (rc != pcmk_rc_ok) {
84 crm_warn("Could not notify client %s: %s " CRM_XS " id=%s",
85 pcmk__client_name(client), pcmk_rc_str(rc),
86 client->id);
87 }
88 break;
89 #ifdef HAVE_GNUTLS_GNUTLS_H
90 case pcmk__client_tls:
91 #endif
92 case pcmk__client_tcp:
93 crm_debug("Sent %s notification to client %s (id %s)",
94 type, pcmk__client_name(client), client->id);
95 pcmk__remote_send_xml(client->remote, update->msg);
96 break;
97 default:
98 crm_err("Unknown transport for client %s "
99 CRM_XS " flags=%#016" PRIx64,
100 pcmk__client_name(client), client->flags);
101 }
102 }
103 }
104
105 static void
106 cib_notify_send(const xmlNode *xml)
107 {
108 struct iovec *iov;
109 struct cib_notification_s update;
110
111 ssize_t bytes = 0;
112 int rc = pcmk__ipc_prepare_iov(0, xml, 0, &iov, &bytes);
113
114 if (rc == pcmk_rc_ok) {
115 update.msg = xml;
116 update.iov = iov;
117 update.iov_size = bytes;
118 pcmk__foreach_ipc_client(cib_notify_send_one, &update);
119
120 } else {
121 crm_notice("Could not notify clients: %s " CRM_XS " rc=%d",
122 pcmk_rc_str(rc), rc);
123 }
124 pcmk_free_ipc_event(iov);
125 }
126
127 static void
128 attach_cib_generation(xmlNode *msg, const char *field, xmlNode *a_cib)
129 {
130 xmlNode *generation = create_xml_node(NULL, XML_CIB_TAG_GENERATION_TUPPLE);
131
132 if (a_cib != NULL) {
133 copy_in_properties(generation, a_cib);
134 }
135 add_message_xml(msg, field, generation);
136 free_xml(generation);
137 }
138
139 void
140 cib_diff_notify(const char *op, int result, const char *call_id,
141 const char *client_id, const char *client_name,
142 const char *origin, xmlNode *update, xmlNode *diff)
143 {
144 int add_updates = 0;
145 int add_epoch = 0;
146 int add_admin_epoch = 0;
147
148 int del_updates = 0;
149 int del_epoch = 0;
150 int del_admin_epoch = 0;
151
152 uint8_t log_level = LOG_TRACE;
153
154 xmlNode *update_msg = NULL;
155 const char *type = NULL;
156
157 if (diff == NULL) {
158 return;
159 }
160
161 if (result != pcmk_ok) {
162 log_level = LOG_WARNING;
163 }
164
165 cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
166 &del_admin_epoch, &del_epoch, &del_updates);
167
168 if ((add_admin_epoch != del_admin_epoch)
169 || (add_epoch != del_epoch)
170 || (add_updates != del_updates)) {
171
172 do_crm_log(log_level,
173 "Updated CIB generation %d.%d.%d to %d.%d.%d from client "
174 "%s%s%s (%s) (%s)",
175 del_admin_epoch, del_epoch, del_updates,
176 add_admin_epoch, add_epoch, add_updates,
177 client_name,
178 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
179 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
180
181 } else if ((add_admin_epoch != 0)
182 || (add_epoch != 0)
183 || (add_updates != 0)) {
184
185 do_crm_log(log_level,
186 "Local-only change to CIB generation %d.%d.%d from client "
187 "%s%s%s (%s) (%s)",
188 add_admin_epoch, add_epoch, add_updates,
189 client_name,
190 ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
191 pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
192 }
193
194 update_msg = create_xml_node(NULL, "notify");
195
196 crm_xml_add(update_msg, F_TYPE, T_CIB_NOTIFY);
197 crm_xml_add(update_msg, F_SUBTYPE, T_CIB_DIFF_NOTIFY);
198 crm_xml_add(update_msg, F_CIB_OPERATION, op);
199 crm_xml_add(update_msg, F_CIB_CLIENTID, client_id);
200 crm_xml_add(update_msg, F_CIB_CLIENTNAME, client_name);
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 = (const char *) update->name;
207 crm_trace("Setting type to update->name: %s", type);
208 } else {
209 type = (const char *) diff->name;
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 crm_log_xml_trace(update_msg, "diff-notify");
222 cib_notify_send(update_msg);
223 free_xml(update_msg);
224 }