selftest: Add a variable to indicate that selftest is running
[ambi/samba-autobuild/.git] / ctdb / common / ctdb_util.c
1 /* 
2    ctdb utility code
3
4    Copyright (C) Andrew Tridgell  2006
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22 #include "system/filesys.h"
23 #include "system/wait.h"
24
25 #include <tdb.h>
26
27 #include "lib/util/debug.h"
28 #include "lib/util/samba_util.h"
29
30 #include "ctdb_private.h"
31
32 #include "common/reqid.h"
33 #include "common/system.h"
34 #include "common/common.h"
35 #include "common/logging.h"
36
37 /*
38   return error string for last error
39 */
40 const char *ctdb_errstr(struct ctdb_context *ctdb)
41 {
42         return ctdb->err_msg;
43 }
44
45
46 /*
47   remember an error message
48 */
49 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...)
50 {
51         va_list ap;
52         talloc_free(ctdb->err_msg);
53         va_start(ap, fmt);
54         ctdb->err_msg = talloc_vasprintf(ctdb, fmt, ap);
55         DEBUG(DEBUG_ERR,("ctdb error: %s\n", ctdb->err_msg));
56         va_end(ap);
57 }
58
59 /*
60   a fatal internal error occurred - no hope for recovery
61 */
62 void ctdb_fatal(struct ctdb_context *ctdb, const char *msg)
63 {
64         DEBUG(DEBUG_ALERT,("ctdb fatal error: %s\n", msg));
65         abort();
66 }
67
68 /*
69   like ctdb_fatal() but a core/backtrace would not be useful
70 */
71 void ctdb_die(struct ctdb_context *ctdb, const char *msg)
72 {
73         DEBUG(DEBUG_ALERT,("ctdb exiting with error: %s\n", msg));
74         exit(1);
75 }
76
77 /* Set the path of a helper program from envvar, falling back to
78  * dir/file if envvar unset. type is a string to print in log
79  * messages.  helper is assumed to point to a statically allocated
80  * array of size bytes, initialised to "".  If file is NULL don't fall
81  * back if envvar is unset.  If dir is NULL and envvar is unset (but
82  * file is not NULL) then this is an error.  Returns true if helper is
83  * set, either previously or this time. */
84 bool ctdb_set_helper(const char *type, char *helper, size_t size,
85                      const char *envvar,
86                      const char *dir, const char *file)
87 {
88         const char *t;
89         struct stat st;
90
91         if (helper[0] != '\0') {
92                 /* Already set */
93                 return true;
94         }
95
96         t = getenv(envvar);
97         if (t != NULL) {
98                 if (strlen(t) >= size) {
99                         DEBUG(DEBUG_ERR,
100                               ("Unable to set %s - path too long\n", type));
101                         return false;
102                 }
103
104                 strncpy(helper, t, size);
105         } else if (file == NULL) {
106                 return false;
107         } else if (dir == NULL) {
108                         DEBUG(DEBUG_ERR,
109                               ("Unable to set %s - dir is NULL\n", type));
110                 return false;
111         } else {
112                 if (snprintf(helper, size, "%s/%s", dir, file) >= size) {
113                         DEBUG(DEBUG_ERR,
114                               ("Unable to set %s - path too long\n", type));
115                         return false;
116                 }
117         }
118
119         if (stat(helper, &st) != 0) {
120                 DEBUG(DEBUG_ERR,
121                       ("Unable to set %s \"%s\" - %s\n",
122                        type, helper, strerror(errno)));
123                 return false;
124         }
125         if (!(st.st_mode & S_IXUSR)) {
126                 DEBUG(DEBUG_ERR,
127                       ("Unable to set %s \"%s\" - not executable\n",
128                        type, helper));
129                 return false;
130         }
131
132         DEBUG(DEBUG_NOTICE,
133               ("Set %s to \"%s\"\n", type, helper));
134         return true;
135 }
136
137 /* Invoke an external program to do some sort of tracing on the CTDB
138  * process.  This might block for a little while.  The external
139  * program is specified by the environment variable
140  * CTDB_EXTERNAL_TRACE.  This program should take one argument: the
141  * pid of the process to trace.  Commonly, the program would be a
142  * wrapper script around gcore.
143  */
144 void ctdb_external_trace(void)
145 {
146         int ret;
147         static char external_trace[PATH_MAX+1] = "";
148         char * cmd;
149
150         if (!ctdb_set_helper("external trace handler",
151                              external_trace, sizeof(external_trace),
152                              "CTDB_EXTERNAL_TRACE", NULL, NULL)) {
153                 return;
154         }
155
156         cmd = talloc_asprintf(NULL, "%s %lu", external_trace, (unsigned long) getpid());
157         DEBUG(DEBUG_WARNING,("begin external trace: %s\n", cmd));
158         ret = system(cmd);
159         if (ret == -1) {
160                 DEBUG(DEBUG_ERR,
161                       ("external trace command \"%s\" failed\n", cmd));
162         }
163         DEBUG(DEBUG_WARNING,("end external trace: %s\n", cmd));
164         talloc_free(cmd);
165 }
166
167 /*
168   parse a IP:port pair
169 */
170 int ctdb_parse_address(TALLOC_CTX *mem_ctx, const char *str,
171                        ctdb_sock_addr *address)
172 {
173         struct servent *se;
174         int port;
175
176         setservent(0);
177         se = getservbyname("ctdb", "tcp");
178         endservent();
179
180         if (se == NULL) {
181                 port = CTDB_PORT;
182         } else {
183                 port = ntohs(se->s_port);
184         }
185
186         if (! parse_ip(str, NULL, port, address)) {
187                 return -1;
188         }
189
190         return 0;
191 }
192
193
194 /*
195   check if two addresses are the same
196 */
197 bool ctdb_same_address(ctdb_sock_addr *a1, ctdb_sock_addr *a2)
198 {
199         return ctdb_same_ip(a1, a2) &&
200                 ctdb_addr_to_port(a1) == ctdb_addr_to_port(a2);
201 }
202
203
204 /*
205   hash function for mapping data to a VNN - taken from tdb
206 */
207 uint32_t ctdb_hash(const TDB_DATA *key)
208 {
209         return tdb_jenkins_hash(discard_const(key));
210 }
211
212
213 static uint32_t ctdb_marshall_record_size(TDB_DATA key,
214                                           struct ctdb_ltdb_header *header,
215                                           TDB_DATA data)
216 {
217         return offsetof(struct ctdb_rec_data_old, data) + key.dsize +
218                data.dsize + (header ? sizeof(*header) : 0);
219 }
220
221 static void ctdb_marshall_record_copy(struct ctdb_rec_data_old *rec,
222                                       uint32_t reqid,
223                                       TDB_DATA key,
224                                       struct ctdb_ltdb_header *header,
225                                       TDB_DATA data,
226                                       uint32_t length)
227 {
228         uint32_t offset;
229
230         rec->length = length;
231         rec->reqid = reqid;
232         rec->keylen = key.dsize;
233         memcpy(&rec->data[0], key.dptr, key.dsize);
234         offset = key.dsize;
235
236         if (header) {
237                 rec->datalen = data.dsize + sizeof(*header);
238                 memcpy(&rec->data[offset], header, sizeof(*header));
239                 offset += sizeof(*header);
240         } else {
241                 rec->datalen = data.dsize;
242         }
243         memcpy(&rec->data[offset], data.dptr, data.dsize);
244 }
245
246 /*
247   form a ctdb_rec_data record from a key/data pair
248   
249   note that header may be NULL. If not NULL then it is included in the data portion
250   of the record
251  */
252 struct ctdb_rec_data_old *ctdb_marshall_record(TALLOC_CTX *mem_ctx,
253                                                uint32_t reqid,
254                                                TDB_DATA key,
255                                                struct ctdb_ltdb_header *header,
256                                                TDB_DATA data)
257 {
258         size_t length;
259         struct ctdb_rec_data_old *d;
260
261         length = ctdb_marshall_record_size(key, header, data);
262
263         d = (struct ctdb_rec_data_old *)talloc_size(mem_ctx, length);
264         if (d == NULL) {
265                 return NULL;
266         }
267
268         ctdb_marshall_record_copy(d, reqid, key, header, data, length);
269         return d;
270 }
271
272
273 /* helper function for marshalling multiple records */
274 struct ctdb_marshall_buffer *ctdb_marshall_add(TALLOC_CTX *mem_ctx,
275                                                struct ctdb_marshall_buffer *m,
276                                                uint32_t db_id,
277                                                uint32_t reqid,
278                                                TDB_DATA key,
279                                                struct ctdb_ltdb_header *header,
280                                                TDB_DATA data)
281 {
282         struct ctdb_rec_data_old *r;
283         struct ctdb_marshall_buffer *m2;
284         uint32_t length, offset;
285
286         length = ctdb_marshall_record_size(key, header, data);
287
288         if (m == NULL) {
289                 offset = offsetof(struct ctdb_marshall_buffer, data);
290                 m2 = talloc_zero_size(mem_ctx, offset + length);
291         } else {
292                 offset = talloc_get_size(m);
293                 m2 = talloc_realloc_size(mem_ctx, m, offset + length);
294         }
295         if (m2 == NULL) {
296                 TALLOC_FREE(m);
297                 return NULL;
298         }
299
300         if (m == NULL) {
301                 m2->db_id = db_id;
302         }
303
304         r = (struct ctdb_rec_data_old *)((uint8_t *)m2 + offset);
305         ctdb_marshall_record_copy(r, reqid, key, header, data, length);
306         m2->count++;
307
308         return m2;
309 }
310
311 /* we've finished marshalling, return a data blob with the marshalled records */
312 TDB_DATA ctdb_marshall_finish(struct ctdb_marshall_buffer *m)
313 {
314         TDB_DATA data;
315         data.dptr = (uint8_t *)m;
316         data.dsize = talloc_get_size(m);
317         return data;
318 }
319
320 /* 
321    loop over a marshalling buffer 
322    
323      - pass r==NULL to start
324      - loop the number of times indicated by m->count
325 */
326 struct ctdb_rec_data_old *ctdb_marshall_loop_next(
327                                 struct ctdb_marshall_buffer *m,
328                                 struct ctdb_rec_data_old *r,
329                                 uint32_t *reqid,
330                                 struct ctdb_ltdb_header *header,
331                                 TDB_DATA *key, TDB_DATA *data)
332 {
333         if (r == NULL) {
334                 r = (struct ctdb_rec_data_old *)&m->data[0];
335         } else {
336                 r = (struct ctdb_rec_data_old *)(r->length + (uint8_t *)r);
337         }
338
339         if (reqid != NULL) {
340                 *reqid = r->reqid;
341         }
342         
343         if (key != NULL) {
344                 key->dptr   = &r->data[0];
345                 key->dsize  = r->keylen;
346         }
347         if (data != NULL) {
348                 data->dptr  = &r->data[r->keylen];
349                 data->dsize = r->datalen;
350                 if (header != NULL) {
351                         data->dptr += sizeof(*header);
352                         data->dsize -= sizeof(*header);
353                 }
354         }
355
356         if (header != NULL) {
357                 if (r->datalen < sizeof(*header)) {
358                         return NULL;
359                 }
360                 memcpy(header, &r->data[r->keylen], sizeof(*header));
361         }
362
363         return r;
364 }
365
366 /*
367    This is used to canonicalize a ctdb_sock_addr structure.
368 */
369 void ctdb_canonicalize_ip(const ctdb_sock_addr *ip, ctdb_sock_addr *cip)
370 {
371         char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff };
372
373         memcpy(cip, ip, sizeof (*cip));
374
375         if ( (ip->sa.sa_family == AF_INET6)
376         && !memcmp(&ip->ip6.sin6_addr, prefix, 12)) {
377                 memset(cip, 0, sizeof(*cip));
378 #ifdef HAVE_SOCK_SIN_LEN
379                 cip->ip.sin_len = sizeof(*cip);
380 #endif
381                 cip->ip.sin_family = AF_INET;
382                 cip->ip.sin_port   = ip->ip6.sin6_port;
383                 memcpy(&cip->ip.sin_addr, &ip->ip6.sin6_addr.s6_addr[12], 4);
384         }
385 }
386
387 bool ctdb_same_ip(const ctdb_sock_addr *tip1, const ctdb_sock_addr *tip2)
388 {
389         ctdb_sock_addr ip1, ip2;
390
391         ctdb_canonicalize_ip(tip1, &ip1);
392         ctdb_canonicalize_ip(tip2, &ip2);
393         
394         if (ip1.sa.sa_family != ip2.sa.sa_family) {
395                 return false;
396         }
397
398         switch (ip1.sa.sa_family) {
399         case AF_INET:
400                 return ip1.ip.sin_addr.s_addr == ip2.ip.sin_addr.s_addr;
401         case AF_INET6:
402                 return !memcmp(&ip1.ip6.sin6_addr.s6_addr[0],
403                                 &ip2.ip6.sin6_addr.s6_addr[0],
404                                 16);
405         default:
406                 DEBUG(DEBUG_ERR, (__location__ " CRITICAL Can not compare sockaddr structures of type %u\n", ip1.sa.sa_family));
407                 return false;
408         }
409
410         return true;
411 }
412
413 /*
414   compare two ctdb_sock_addr structures
415  */
416 bool ctdb_same_sockaddr(const ctdb_sock_addr *ip1, const ctdb_sock_addr *ip2)
417 {
418         return ctdb_same_ip(ip1, ip2) && ip1->ip.sin_port == ip2->ip.sin_port;
419 }
420
421 char *ctdb_addr_to_str(ctdb_sock_addr *addr)
422 {
423         static char cip[128] = "";
424
425         switch (addr->sa.sa_family) {
426         case AF_INET:
427                 inet_ntop(addr->ip.sin_family, &addr->ip.sin_addr, cip, sizeof(cip));
428                 break;
429         case AF_INET6:
430                 inet_ntop(addr->ip6.sin6_family, &addr->ip6.sin6_addr, cip, sizeof(cip));
431                 break;
432         default:
433                 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family %u\n", addr->sa.sa_family));
434                 ctdb_external_trace();
435         }
436
437         return cip;
438 }
439
440 unsigned ctdb_addr_to_port(ctdb_sock_addr *addr)
441 {
442         switch (addr->sa.sa_family) {
443         case AF_INET:
444                 return ntohs(addr->ip.sin_port);
445                 break;
446         case AF_INET6:
447                 return ntohs(addr->ip6.sin6_port);
448                 break;
449         default:
450                 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family %u\n", addr->sa.sa_family));
451         }
452
453         return 0;
454 }
455
456 /* Add a node to a node map with given address and flags */
457 static bool node_map_add(TALLOC_CTX *mem_ctx,
458                          const char *nstr, uint32_t flags,
459                          struct ctdb_node_map_old **node_map)
460 {
461         ctdb_sock_addr addr;
462         uint32_t num;
463         size_t s;
464         struct ctdb_node_and_flags *n;
465
466         /* Might as well do this before trying to allocate memory */
467         if (ctdb_parse_address(mem_ctx, nstr, &addr) == -1) {
468                 return false;
469         }
470
471         num = (*node_map)->num + 1;
472         s = offsetof(struct ctdb_node_map_old, nodes) +
473                 num * sizeof(struct ctdb_node_and_flags);
474         *node_map = talloc_realloc_size(mem_ctx, *node_map, s);
475         if (*node_map == NULL) {
476                 DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
477                 return false;
478         }
479
480         n = &(*node_map)->nodes[(*node_map)->num];
481         n->addr = addr;
482         n->pnn = (*node_map)->num;
483         n->flags = flags;
484
485         (*node_map)->num++;
486
487         return true;
488 }
489
490 /* Read a nodes file into a node map */
491 struct ctdb_node_map_old *ctdb_read_nodes_file(TALLOC_CTX *mem_ctx,
492                                            const char *nlist)
493 {
494         char **lines;
495         int nlines;
496         int i;
497         struct ctdb_node_map_old *ret;
498
499         /* Allocate node map header */
500         ret = talloc_zero_size(mem_ctx, offsetof(struct ctdb_node_map_old, nodes));
501         if (ret == NULL) {
502                 DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
503                 return false;
504         }
505
506         lines = file_lines_load(nlist, &nlines, 0, mem_ctx);
507         if (lines == NULL) {
508                 DEBUG(DEBUG_ERR, ("Failed to read nodes file \"%s\"\n", nlist));
509                 return false;
510         }
511         while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
512                 nlines--;
513         }
514
515         for (i=0; i < nlines; i++) {
516                 char *node;
517                 uint32_t flags;
518                 size_t len;
519
520                 node = lines[i];
521                 /* strip leading spaces */
522                 while((*node == ' ') || (*node == '\t')) {
523                         node++;
524                 }
525
526                 len = strlen(node);
527
528                 while ((len > 1) &&
529                        ((node[len-1] == ' ') || (node[len-1] == '\t')))
530                 {
531                         node[len-1] = '\0';
532                         len--;
533                 }
534
535                 if (len == 0) {
536                         continue;
537                 }
538                 if (*node == '#') {
539                         /* A "deleted" node is a node that is
540                            commented out in the nodes file.  This is
541                            used instead of removing a line, which
542                            would cause subsequent nodes to change
543                            their PNN. */
544                         flags = NODE_FLAGS_DELETED;
545                         node = discard_const("0.0.0.0");
546                 } else {
547                         flags = 0;
548                 }
549                 if (!node_map_add(mem_ctx, node, flags, &ret)) {
550                         talloc_free(lines);
551                         TALLOC_FREE(ret);
552                         return NULL;
553                 }
554         }
555
556         talloc_free(lines);
557         return ret;
558 }
559
560 struct ctdb_node_map_old *
561 ctdb_node_list_to_map(struct ctdb_node **nodes, uint32_t num_nodes,
562                       TALLOC_CTX *mem_ctx)
563 {
564         uint32_t i;
565         size_t size;
566         struct ctdb_node_map_old *node_map;
567
568         size = offsetof(struct ctdb_node_map_old, nodes) +
569                 num_nodes * sizeof(struct ctdb_node_and_flags);
570         node_map  = (struct ctdb_node_map_old *)talloc_zero_size(mem_ctx, size);
571         if (node_map == NULL) {
572                 DEBUG(DEBUG_ERR,
573                       (__location__ " Failed to allocate nodemap array\n"));
574                 return NULL;
575         }
576
577         node_map->num = num_nodes;
578         for (i=0; i<num_nodes; i++) {
579                 node_map->nodes[i].addr  = nodes[i]->address;
580                 node_map->nodes[i].pnn   = nodes[i]->pnn;
581                 node_map->nodes[i].flags = nodes[i]->flags;
582         }
583
584         return node_map;
585 }
586
587 const char *ctdb_eventscript_call_names[] = {
588         "init",
589         "setup",
590         "startup",
591         "startrecovery",
592         "recovered",
593         "takeip",
594         "releaseip",
595         "stopped",
596         "monitor",
597         "status",
598         "shutdown",
599         "reload",
600         "updateip",
601         "ipreallocated"
602 };
603
604 /* Runstate handling */
605 static struct {
606         enum ctdb_runstate runstate;
607         const char * label;
608 } runstate_map[] = {
609         { CTDB_RUNSTATE_UNKNOWN, "UNKNOWN" },
610         { CTDB_RUNSTATE_INIT, "INIT" },
611         { CTDB_RUNSTATE_SETUP, "SETUP" },
612         { CTDB_RUNSTATE_FIRST_RECOVERY, "FIRST_RECOVERY" },
613         { CTDB_RUNSTATE_STARTUP, "STARTUP" },
614         { CTDB_RUNSTATE_RUNNING, "RUNNING" },
615         { CTDB_RUNSTATE_SHUTDOWN, "SHUTDOWN" },
616         { -1, NULL },
617 };
618
619 const char *runstate_to_string(enum ctdb_runstate runstate)
620 {
621         int i;
622         for (i=0; runstate_map[i].label != NULL ; i++) {
623                 if (runstate_map[i].runstate == runstate) {
624                         return runstate_map[i].label;
625                 }
626         }
627
628         return runstate_map[0].label;
629 }
630
631 enum ctdb_runstate runstate_from_string(const char *label)
632 {
633         int i;
634         for (i=0; runstate_map[i].label != NULL; i++) {
635                 if (strcasecmp(runstate_map[i].label, label) == 0) {
636                         return runstate_map[i].runstate;
637                 }
638         }
639
640         return CTDB_RUNSTATE_UNKNOWN;
641 }
642
643 void ctdb_set_runstate(struct ctdb_context *ctdb, enum ctdb_runstate runstate)
644 {
645         DEBUG(DEBUG_NOTICE,("Set runstate to %s (%d)\n",
646                             runstate_to_string(runstate), runstate));
647
648         if (runstate <= ctdb->runstate) {
649                 ctdb_fatal(ctdb, "runstate must always increase");
650         }
651
652         ctdb->runstate = runstate;
653 }
654
655 /* Convert arbitrary data to 4-byte boundary padded uint32 array */
656 uint32_t *ctdb_key_to_idkey(TALLOC_CTX *mem_ctx, TDB_DATA key)
657 {
658         uint32_t idkey_size, *k;
659
660         idkey_size = 1 + (key.dsize + sizeof(uint32_t)-1) / sizeof(uint32_t);
661
662         k = talloc_zero_array(mem_ctx, uint32_t, idkey_size);
663         if (k == NULL) {
664                 return NULL;
665         }
666
667         k[0] = idkey_size;
668         memcpy(&k[1], key.dptr, key.dsize);
669
670         return k;
671 }