14ea6732fefd52a6089933e69320db1225ced3d3
[vlendec/samba-autobuild/.git] / ctdb / common / ctdb_control.c
1 /* 
2    ctdb_control protocol code
3
4    Copyright (C) Andrew Tridgell  2007
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 #include "includes.h"
21 #include "lib/events/events.h"
22 #include "lib/tdb/include/tdb.h"
23 #include "system/network.h"
24 #include "system/filesys.h"
25 #include "system/wait.h"
26 #include "../include/ctdb_private.h"
27 #include "lib/util/dlinklist.h"
28 #include "db_wrap.h"
29
30 struct ctdb_control_state {
31         struct ctdb_context *ctdb;
32         uint32_t reqid;
33         ctdb_control_callback_fn_t callback;
34         void *private_data;
35         unsigned flags;
36 };
37
38 /*
39   process a control request
40  */
41 static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, 
42                                      struct ctdb_req_control *c,
43                                      TDB_DATA indata,
44                                      TDB_DATA *outdata, uint32_t srcnode,
45                                      const char **errormsg,
46                                      bool *async_reply)
47 {
48         uint32_t opcode = c->opcode;
49         uint64_t srvid = c->srvid;
50         uint32_t client_id = c->client_id;
51
52         switch (opcode) {
53         case CTDB_CONTROL_PROCESS_EXISTS: {
54                 CHECK_CONTROL_DATA_SIZE(sizeof(pid_t));
55                 ctdb->statistics.controls.process_exists++;
56                 return kill(*(pid_t *)indata.dptr, 0);
57         }
58
59         case CTDB_CONTROL_SET_DEBUG: {
60                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
61                 LogLevel = *(uint32_t *)indata.dptr;
62                 return 0;
63         }
64
65         case CTDB_CONTROL_GET_DEBUG: {
66                 CHECK_CONTROL_DATA_SIZE(0);
67                 outdata->dptr = (uint8_t *)&LogLevel;
68                 outdata->dsize = sizeof(LogLevel);
69                 return 0;
70         }
71
72         case CTDB_CONTROL_STATISTICS: {
73                 CHECK_CONTROL_DATA_SIZE(0);
74                 ctdb->statistics.controls.statistics++;
75                 ctdb->statistics.memory_used = talloc_total_size(ctdb);
76                 ctdb->statistics.frozen = (ctdb->freeze_mode == CTDB_FREEZE_FROZEN);
77                 ctdb->statistics.recovering = (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE);
78                 outdata->dptr = (uint8_t *)&ctdb->statistics;
79                 outdata->dsize = sizeof(ctdb->statistics);
80                 return 0;
81         }
82
83         case CTDB_CONTROL_DUMP_MEMORY: {
84                 CHECK_CONTROL_DATA_SIZE(0);
85                 talloc_report_full(ctdb, stdout);
86                 return 0;
87         }
88
89         case CTDB_CONTROL_STATISTICS_RESET: {
90                 CHECK_CONTROL_DATA_SIZE(0);
91                 ZERO_STRUCT(ctdb->statistics);
92                 return 0;
93         }
94
95         case CTDB_CONTROL_GETVNNMAP:
96                 return ctdb_control_getvnnmap(ctdb, opcode, indata, outdata);
97
98         case CTDB_CONTROL_GET_DBMAP:
99                 return ctdb_control_getdbmap(ctdb, opcode, indata, outdata);
100
101         case CTDB_CONTROL_GET_NODEMAP:
102                 return ctdb_control_getnodemap(ctdb, opcode, indata, outdata);
103
104         case CTDB_CONTROL_SETVNNMAP:
105                 return ctdb_control_setvnnmap(ctdb, opcode, indata, outdata);
106
107         case CTDB_CONTROL_PULL_DB: 
108                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_pulldb));
109                 return ctdb_control_pull_db(ctdb, indata, outdata);
110
111         case CTDB_CONTROL_SET_DMASTER: 
112                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_set_dmaster));
113                 return ctdb_control_set_dmaster(ctdb, indata);
114
115         case CTDB_CONTROL_CLEAR_DB: 
116                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
117                 return ctdb_control_clear_db(ctdb, indata);
118
119         case CTDB_CONTROL_PUSH_DB:
120                 return ctdb_control_push_db(ctdb, indata);
121
122         case CTDB_CONTROL_GET_RECMODE: {
123                 return ctdb->recovery_mode;
124         }
125
126         case CTDB_CONTROL_SET_RECMASTER: {
127                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
128                 if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
129                         DEBUG(0,("Attempt to set recmaster when not frozen\n"));
130                         return -1;
131                 }
132                 ctdb->recovery_master = ((uint32_t *)(&indata.dptr[0]))[0];
133                 return 0;
134         }
135
136         case CTDB_CONTROL_GET_RECMASTER:
137                 return ctdb->recovery_master;
138
139         case CTDB_CONTROL_GET_PID:
140                 return getpid();
141
142         case CTDB_CONTROL_GET_VNN:
143                 return ctdb->vnn;
144
145         case CTDB_CONTROL_PING:
146                 CHECK_CONTROL_DATA_SIZE(0);
147                 ctdb->statistics.controls.ping++;
148                 return ctdb->statistics.num_clients;
149
150         case CTDB_CONTROL_GET_DBNAME: {
151                 uint32_t db_id;
152                 struct ctdb_db_context *ctdb_db;
153
154                 CHECK_CONTROL_DATA_SIZE(sizeof(db_id));
155                 db_id = *(uint32_t *)indata.dptr;
156                 ctdb_db = find_ctdb_db(ctdb, db_id);
157                 if (ctdb_db == NULL) return -1;
158                 outdata->dptr = discard_const(ctdb_db->db_name);
159                 outdata->dsize = strlen(ctdb_db->db_name)+1;
160                 return 0;
161         }
162
163         case CTDB_CONTROL_GETDBPATH: {
164                 uint32_t db_id;
165                 struct ctdb_db_context *ctdb_db;
166
167                 CHECK_CONTROL_DATA_SIZE(sizeof(db_id));
168                 db_id = *(uint32_t *)indata.dptr;
169                 ctdb_db = find_ctdb_db(ctdb, db_id);
170                 if (ctdb_db == NULL) return -1;
171                 outdata->dptr = discard_const(ctdb_db->db_path);
172                 outdata->dsize = strlen(ctdb_db->db_path)+1;
173                 return 0;
174         }
175
176         case CTDB_CONTROL_DB_ATTACH:
177                 ctdb->statistics.controls.attach++;
178                 return ctdb_control_db_attach(ctdb, indata, outdata);
179
180         case CTDB_CONTROL_SET_CALL: {
181                 struct ctdb_control_set_call *sc = 
182                         (struct ctdb_control_set_call *)indata.dptr;
183                 ctdb->statistics.controls.set_call++;
184                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_set_call));
185                 return ctdb_daemon_set_call(ctdb, sc->db_id, sc->fn, sc->id);
186         }
187
188         case CTDB_CONTROL_TRAVERSE_START:
189                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_traverse_start));
190                 ctdb->statistics.controls.traverse_start++;
191                 return ctdb_control_traverse_start(ctdb, indata, outdata, srcnode);
192
193         case CTDB_CONTROL_TRAVERSE_ALL:
194                 ctdb->statistics.controls.traverse_all++;
195                 return ctdb_control_traverse_all(ctdb, indata, outdata);
196
197         case CTDB_CONTROL_TRAVERSE_DATA:
198                 ctdb->statistics.controls.traverse_data++;
199                 return ctdb_control_traverse_data(ctdb, indata, outdata);
200
201         case CTDB_CONTROL_REGISTER_SRVID:
202                 ctdb->statistics.controls.register_srvid++;
203                 return daemon_register_message_handler(ctdb, client_id, srvid);
204
205         case CTDB_CONTROL_DEREGISTER_SRVID:
206                 ctdb->statistics.controls.deregister_srvid++;
207                 return daemon_deregister_message_handler(ctdb, client_id, srvid);
208
209         case CTDB_CONTROL_ENABLE_SEQNUM:
210                 ctdb->statistics.controls.enable_seqnum++;
211                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
212                 return ctdb_ltdb_enable_seqnum(ctdb, *(uint32_t *)indata.dptr);
213
214         case CTDB_CONTROL_UPDATE_SEQNUM:
215                 ctdb->statistics.controls.update_seqnum++;
216                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
217                 return ctdb_ltdb_update_seqnum(ctdb, *(uint32_t *)indata.dptr, srcnode);
218
219         case CTDB_CONTROL_FREEZE:
220                 CHECK_CONTROL_DATA_SIZE(0);
221                 return ctdb_control_freeze(ctdb, c, async_reply);
222
223         case CTDB_CONTROL_THAW:
224                 CHECK_CONTROL_DATA_SIZE(0);
225                 return ctdb_control_thaw(ctdb);
226
227         case CTDB_CONTROL_SET_RECMODE:
228                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
229                 return ctdb_control_set_recmode(ctdb, c, indata, async_reply, errormsg);
230
231         case CTDB_CONTROL_SET_MONMODE:
232                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
233                 ctdb->monitoring_mode = *(uint32_t *)indata.dptr;
234                 return 0;
235
236         case CTDB_CONTROL_GET_MONMODE: 
237                 return ctdb->monitoring_mode;
238
239         case CTDB_CONTROL_SHUTDOWN:
240                 ctdb_release_all_ips(ctdb);
241                 ctdb->methods->shutdown(ctdb);
242                 ctdb_event_script(ctdb, "shutdown");
243                 DEBUG(0,("shutting down\n"));
244                 exit(0);
245
246         case CTDB_CONTROL_MAX_RSN: 
247                 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
248                 return ctdb_control_max_rsn(ctdb, indata, outdata);
249
250         case CTDB_CONTROL_SET_RSN_NONEMPTY: 
251                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_set_rsn_nonempty));
252                 return ctdb_control_set_rsn_nonempty(ctdb, indata, outdata);
253
254         case CTDB_CONTROL_TAKEOVER_IP:
255                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_public_ip));
256                 return ctdb_control_takeover_ip(ctdb, c, indata, async_reply);
257
258         case CTDB_CONTROL_RELEASE_IP:
259                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_public_ip));
260                 return ctdb_control_release_ip(ctdb, c, indata, async_reply);
261
262         case CTDB_CONTROL_GET_PUBLIC_IPS:
263                 CHECK_CONTROL_DATA_SIZE(0);
264                 return ctdb_control_get_public_ips(ctdb, c, outdata);
265
266         case CTDB_CONTROL_DELETE_LOW_RSN: 
267                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_delete_low_rsn));
268                 return ctdb_control_delete_low_rsn(ctdb, indata, outdata);
269
270         case CTDB_CONTROL_TCP_CLIENT: 
271                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp));
272                 return ctdb_control_tcp_client(ctdb, client_id, srcnode, indata);
273
274         case CTDB_CONTROL_STARTUP: 
275                 CHECK_CONTROL_DATA_SIZE(0);
276                 return ctdb_control_startup(ctdb, srcnode);
277
278         case CTDB_CONTROL_TCP_ADD: 
279                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp_vnn));
280                 return ctdb_control_tcp_add(ctdb, indata);
281
282         case CTDB_CONTROL_TCP_REMOVE: 
283                 CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp_vnn));
284                 return ctdb_control_tcp_remove(ctdb, indata);
285
286         case CTDB_CONTROL_SET_TUNABLE:
287                 return ctdb_control_set_tunable(ctdb, indata);
288
289         case CTDB_CONTROL_GET_TUNABLE:
290                 return ctdb_control_get_tunable(ctdb, indata, outdata);
291
292         case CTDB_CONTROL_LIST_TUNABLES:
293                 return ctdb_control_list_tunables(ctdb, outdata);
294
295         default:
296                 DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode));
297                 return -1;
298         }
299 }
300
301
302 /*
303   send a reply for a ctdb control
304  */
305 void ctdb_request_control_reply(struct ctdb_context *ctdb, struct ctdb_req_control *c,
306                                 TDB_DATA *outdata, int32_t status, const char *errormsg)
307 {
308         struct ctdb_reply_control *r;
309         size_t len;
310         
311         /* some controls send no reply */
312         if (c->flags & CTDB_CTRL_FLAG_NOREPLY) {
313                 return;
314         }
315
316         len = offsetof(struct ctdb_reply_control, data) + (outdata?outdata->dsize:0);
317         if (errormsg) {
318                 len += strlen(errormsg);
319         }
320         r = ctdb_transport_allocate(ctdb, ctdb, CTDB_REPLY_CONTROL, len, struct ctdb_reply_control);
321         CTDB_NO_MEMORY_VOID(ctdb, r);
322
323         r->hdr.destnode     = c->hdr.srcnode;
324         r->hdr.reqid        = c->hdr.reqid;
325         r->status           = status;
326         r->datalen          = outdata?outdata->dsize:0;
327         if (outdata && outdata->dsize) {
328                 memcpy(&r->data[0], outdata->dptr, outdata->dsize);
329         }
330         if (errormsg) {
331                 r->errorlen = strlen(errormsg);
332                 memcpy(&r->data[r->datalen], errormsg, r->errorlen);
333         }
334         
335         ctdb_queue_packet(ctdb, &r->hdr);       
336
337         talloc_free(r);
338 }
339
340 /*
341   called when a CTDB_REQ_CONTROL packet comes in
342 */
343 void ctdb_request_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
344 {
345         struct ctdb_req_control *c = (struct ctdb_req_control *)hdr;
346         TDB_DATA data, *outdata;
347         int32_t status;
348         bool async_reply = False;
349         const char *errormsg = NULL;
350
351         data.dptr = &c->data[0];
352         data.dsize = c->datalen;
353
354         outdata = talloc_zero(c, TDB_DATA);
355
356         status = ctdb_control_dispatch(ctdb, c, data, outdata, hdr->srcnode, 
357                                        &errormsg, &async_reply);
358
359         if (!async_reply) {
360                 ctdb_request_control_reply(ctdb, c, outdata, status, errormsg);
361         }
362 }
363
364 /*
365   called when a CTDB_REPLY_CONTROL packet comes in
366 */
367 void ctdb_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
368 {
369         struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr;
370         TDB_DATA data;
371         struct ctdb_control_state *state;
372         const char *errormsg = NULL;
373
374         state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_control_state);
375         if (state == NULL) {
376                 DEBUG(0,("vnn %u Invalid reqid %u in ctdb_reply_control\n",
377                          ctdb->vnn, hdr->reqid));
378                 return;
379         }
380
381         if (hdr->reqid != state->reqid) {
382                 /* we found a record  but it was the wrong one */
383                 DEBUG(0, ("Dropped orphaned control reply with reqid:%u\n", hdr->reqid));
384                 return;
385         }
386
387         data.dptr = &c->data[0];
388         data.dsize = c->datalen;
389         if (c->errorlen) {
390                 errormsg = talloc_strndup(state, 
391                                           (char *)&c->data[c->datalen], c->errorlen);
392         }
393
394         /* make state a child of the packet, so it goes away when the packet
395            is freed. */
396         talloc_steal(hdr, state);
397
398         state->callback(ctdb, c->status, data, errormsg, state->private_data);
399 }
400
401 static int ctdb_control_destructor(struct ctdb_control_state *state)
402 {
403         ctdb_reqid_remove(state->ctdb, state->reqid);
404         return 0;
405 }
406
407 /*
408   handle a timeout of a control
409  */
410 static void ctdb_control_timeout(struct event_context *ev, struct timed_event *te, 
411                        struct timeval t, void *private_data)
412 {
413         struct ctdb_control_state *state = talloc_get_type(private_data, struct ctdb_control_state);
414         TALLOC_CTX *tmp_ctx = talloc_new(ev);
415
416         state->ctdb->statistics.timeouts.control++;
417
418         talloc_steal(tmp_ctx, state);
419
420         state->callback(state->ctdb, -1, tdb_null,
421                         "ctdb_control timed out", 
422                         state->private_data);
423         talloc_free(tmp_ctx);
424 }
425
426
427 /*
428   send a control message to a node
429  */
430 int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
431                              uint64_t srvid, uint32_t opcode, uint32_t client_id,
432                              uint32_t flags,
433                              TDB_DATA data,
434                              ctdb_control_callback_fn_t callback,
435                              void *private_data)
436 {
437         struct ctdb_req_control *c;
438         struct ctdb_control_state *state;
439         size_t len;
440
441         if (((destnode == CTDB_BROADCAST_VNNMAP) || (destnode == CTDB_BROADCAST_VNNMAP)) && !(flags & CTDB_CTRL_FLAG_NOREPLY)) {
442                 DEBUG(0,("Attempt to broadcast control without NOREPLY\n"));
443                 return -1;
444         }
445
446         if (destnode != CTDB_BROADCAST_VNNMAP && destnode != CTDB_BROADCAST_ALL && 
447             (!ctdb_validate_vnn(ctdb, destnode) || 
448              !(ctdb->nodes[destnode]->flags & NODE_FLAGS_CONNECTED))) {
449                 if (!(flags & CTDB_CTRL_FLAG_NOREPLY)) {
450                         callback(ctdb, -1, tdb_null, "ctdb_control to disconnected node", private_data);
451                 }
452                 return 0;
453         }
454
455         /* the state is made a child of private_data if possible. This means any reply
456            will be discarded if the private_data goes away */
457         state = talloc(private_data?private_data:ctdb, struct ctdb_control_state);
458         CTDB_NO_MEMORY(ctdb, state);
459
460         state->reqid = ctdb_reqid_new(ctdb, state);
461         state->callback = callback;
462         state->private_data = private_data;
463         state->ctdb = ctdb;
464         state->flags = flags;
465
466         talloc_set_destructor(state, ctdb_control_destructor);
467
468         len = offsetof(struct ctdb_req_control, data) + data.dsize;
469         c = ctdb_transport_allocate(ctdb, state, CTDB_REQ_CONTROL, len, 
470                                     struct ctdb_req_control);
471         CTDB_NO_MEMORY(ctdb, c);
472         talloc_set_name_const(c, "ctdb_req_control packet");
473
474         c->hdr.destnode     = destnode;
475         c->hdr.reqid        = state->reqid;
476         c->opcode           = opcode;
477         c->client_id        = client_id;
478         c->flags            = flags;
479         c->srvid            = srvid;
480         c->datalen          = data.dsize;
481         if (data.dsize) {
482                 memcpy(&c->data[0], data.dptr, data.dsize);
483         }
484
485         ctdb_queue_packet(ctdb, &c->hdr);       
486
487         if (flags & CTDB_CTRL_FLAG_NOREPLY) {
488                 talloc_free(state);
489                 return 0;
490         }
491
492         if (ctdb->tunable.control_timeout) {
493                 event_add_timed(ctdb->ev, state, 
494                                 timeval_current_ofs(ctdb->tunable.control_timeout, 0), 
495                                 ctdb_control_timeout, state);
496         }
497
498         talloc_free(c);
499         return 0;
500 }