From: Andrew Tridgell Date: Mon, 30 Apr 2007 20:34:55 +0000 (+1000) Subject: auto-determine listen address by attempting to bind to each address in the cluster... X-Git-Tag: tevent-0.9.20~348^2~2805 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5b8c4bba5a9477fb232381f5d03f106ff1ebdf3e;p=thirdparty%2Fsamba.git auto-determine listen address by attempting to bind to each address in the cluster in turn (This used to be ctdb commit 2fab9f96df2e5b5c51c860fd65caf0e926a63e34) --- diff --git a/ctdb/Makefile.in b/ctdb/Makefile.in index 71c45ce6b30..9254ff8120a 100644 --- a/ctdb/Makefile.in +++ b/ctdb/Makefile.in @@ -112,10 +112,10 @@ install: all rsync $(BINS) $(bindir) rsync $(srcdir)/include/ctdb.h $(includedir) -test: +test: all tests/run_tests.sh -valgrindtest: +valgrindtest: all VALGRIND="valgrind -q --trace-children=yes" tests/run_tests.sh diff --git a/ctdb/common/cmdline.c b/ctdb/common/cmdline.c index 4ffb032ed1e..23c93edea12 100644 --- a/ctdb/common/cmdline.c +++ b/ctdb/common/cmdline.c @@ -71,8 +71,8 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev) struct ctdb_context *ctdb; int i, ret; - if (ctdb_cmdline.nlist == NULL || ctdb_cmdline.myaddress == NULL) { - printf("You must provide a node list with --nlist and an address with --listen\n"); + if (ctdb_cmdline.nlist == NULL) { + printf("You must provide a node list with --nlist\n"); exit(1); } @@ -103,10 +103,12 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev) } /* tell ctdb what address to listen on */ - ret = ctdb_set_address(ctdb, ctdb_cmdline.myaddress); - if (ret == -1) { - printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb)); - exit(1); + if (ctdb_cmdline.myaddress) { + ret = ctdb_set_address(ctdb, ctdb_cmdline.myaddress); + if (ret == -1) { + printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb)); + exit(1); + } } /* tell ctdb the socket address */ @@ -123,10 +125,12 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev) exit(1); } - ret = ctdb_set_tdb_dir(ctdb, ctdb_cmdline.db_dir); - if (ret == -1) { - printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb)); - exit(1); + if (ctdb_cmdline.db_dir) { + ret = ctdb_set_tdb_dir(ctdb, ctdb_cmdline.db_dir); + if (ret == -1) { + printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb)); + exit(1); + } } /* initialize the vnn mapping table */ diff --git a/ctdb/common/ctdb.c b/ctdb/common/ctdb.c index 69e69ec8ca2..0e7ea3818d9 100644 --- a/ctdb/common/ctdb.c +++ b/ctdb/common/ctdb.c @@ -86,11 +86,7 @@ void ctdb_set_max_lacount(struct ctdb_context *ctdb, unsigned count) */ int ctdb_set_tdb_dir(struct ctdb_context *ctdb, const char *dir) { - if (dir == NULL) { - ctdb->db_directory = talloc_asprintf(ctdb, "ctdb-%u", ctdb_get_vnn(ctdb)); - } else { - ctdb->db_directory = talloc_strdup(ctdb, dir); - } + ctdb->db_directory = talloc_strdup(ctdb, dir); if (ctdb->db_directory == NULL) { return -1; } @@ -124,7 +120,8 @@ static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr) will change! */ node->vnn = ctdb->num_nodes; - if (ctdb_same_address(&ctdb->address, &node->address)) { + if (ctdb->address.address && + ctdb_same_address(&ctdb->address, &node->address)) { ctdb->vnn = node->vnn; node->flags |= NODE_FLAGS_CONNECTED; } diff --git a/ctdb/common/ctdb_daemon.c b/ctdb/common/ctdb_daemon.c index e994e76147e..af6222b4fad 100644 --- a/ctdb/common/ctdb_daemon.c +++ b/ctdb/common/ctdb_daemon.c @@ -653,6 +653,7 @@ int ctdb_start(struct ctdb_context *ctdb) close(fd[0]); close(ctdb->daemon.sd); ctdb->daemon.sd = -1; + ctdb_get_config(ctdb); return 0; } diff --git a/ctdb/common/ctdb_ltdb.c b/ctdb/common/ctdb_ltdb.c index 2cf90a177c8..e071a20590a 100644 --- a/ctdb/common/ctdb_ltdb.c +++ b/ctdb/common/ctdb_ltdb.c @@ -301,6 +301,8 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, for (tmp_db=ctdb->db_list;tmp_db;tmp_db=tmp_db->next) { if (strcmp(db_name, tmp_db->db_name) == 0) { /* this is not an error */ + outdata->dptr = (uint8_t *)&tmp_db->db_id; + outdata->dsize = sizeof(tmp_db->db_id); return 0; } } @@ -327,6 +329,10 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, } } + if (ctdb->db_directory == NULL) { + ctdb->db_directory = VARDIR "/ctdb"; + } + /* make sure the db directory exists */ if (mkdir(ctdb->db_directory, 0700) == -1 && errno != EEXIST) { DEBUG(0,(__location__ " Unable to create ctdb directory '%s'\n", @@ -336,8 +342,9 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, } /* open the database */ - ctdb_db->db_path = talloc_asprintf(ctdb_db, "%s/%s", - ctdb->db_directory, db_name); + ctdb_db->db_path = talloc_asprintf(ctdb_db, "%s/%s.%u", + ctdb->db_directory, + db_name, ctdb->vnn); ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0666); @@ -365,6 +372,8 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, CTDB_CONTROL_DB_ATTACH, CTDB_CTRL_FLAG_NOREPLY, indata, NULL, NULL); + DEBUG(0,("Attached to database '%s'\n", ctdb_db->db_path)); + /* success */ return 0; } diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 4d9d8e83868..30d87001afe 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -205,46 +205,134 @@ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde, /* - listen on our own address + automatically find which address to listen on */ -int ctdb_tcp_listen(struct ctdb_context *ctdb) +static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); struct sockaddr_in sock; - int one = 1; + int lock_fd, i; + const char *lock_path = "/tmp/.ctdb_socket_lock"; + struct flock lock; + + /* in order to ensure that we don't get two nodes with the + same adddress, we must make the bind() and listen() calls + atomic. The SO_REUSEADDR setsockopt only prevents double + binds if the first socket is in LISTEN state */ + lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666); + if (lock_fd == -1) { + DEBUG(0,("Unable to open %s\n", lock_path)); + return -1; + } + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + lock.l_pid = 0; - sock.sin_port = htons(ctdb->address.port); - sock.sin_family = PF_INET; - if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock.sin_addr) != 0) { + if (fcntl(lock_fd, F_SETLKW, &lock) != 0) { + DEBUG(0,("Unable to lock %s\n", lock_path)); + close(lock_fd); return -1; } - ctcp->listen_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ctcp->listen_fd == -1) { + for (i=0;inum_nodes;i++) { + sock.sin_port = htons(ctdb->nodes[i]->address.port); + sock.sin_family = PF_INET; + if (ctdb_tcp_get_address(ctdb, ctdb->nodes[i]->address.address, + &sock.sin_addr) != 0) { + continue; + } + + if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, + sizeof(sock)) == 0) { + break; + } + } + + if (i == ctdb->num_nodes) { + DEBUG(0,("Unable to bind to any of the node addresses - giving up\n")); + goto failed; + } + ctdb->address = ctdb->nodes[i]->address; + ctdb->name = talloc_asprintf(ctdb, "%s:%u", + ctdb->address.address, + ctdb->address.port); + ctdb->vnn = ctdb->nodes[i]->vnn; + ctdb->nodes[i]->flags |= NODE_FLAGS_CONNECTED; + DEBUG(0,("ctdb chose network address %s:%u vnn %u\n", + ctdb->address.address, + ctdb->address.port, + ctdb->vnn)); + + if (listen(ctcp->listen_fd, 10) == -1) { + goto failed; + } + + event_add_fd(ctdb->ev, ctdb, ctcp->listen_fd, EVENT_FD_READ, + ctdb_listen_event, ctdb); + + close(lock_fd); + return 0; + +failed: + close(lock_fd); + close(ctcp->listen_fd); + ctcp->listen_fd = -1; + return -1; +} + + +/* + listen on our own address +*/ +int ctdb_tcp_listen(struct ctdb_context *ctdb) +{ + struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, + struct ctdb_tcp); + struct sockaddr_in sock; + int one = 1; + + ctcp->listen_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (ctcp->listen_fd == -1) { ctdb_set_error(ctdb, "socket failed\n"); return -1; - } + } setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); - if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) { - ctdb_set_error(ctdb, "bind failed\n"); - close(ctcp->listen_fd); - ctcp->listen_fd = -1; - return -1; - } + /* we can either auto-bind to the first available address, or we can + use a specified address */ + if (!ctdb->address.address) { + return ctdb_tcp_listen_automatic(ctdb); + } + + sock.sin_port = htons(ctdb->address.port); + sock.sin_family = PF_INET; + + if (ctdb_tcp_get_address(ctdb, ctdb->address.address, + &sock.sin_addr) != 0) { + goto failed; + } + + if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) { + goto failed; + } if (listen(ctcp->listen_fd, 10) == -1) { - ctdb_set_error(ctdb, "listen failed\n"); - close(ctcp->listen_fd); - ctcp->listen_fd = -1; - return -1; + goto failed; } event_add_fd(ctdb->ev, ctdb, ctcp->listen_fd, EVENT_FD_READ, ctdb_listen_event, ctdb); return 0; + +failed: + close(ctcp->listen_fd); + ctcp->listen_fd = -1; + return -1; } diff --git a/ctdb/tests/bench-ssh.sh b/ctdb/tests/bench-ssh.sh index e9b1ec28d0e..8716156e3aa 100755 --- a/ctdb/tests/bench-ssh.sh +++ b/ctdb/tests/bench-ssh.sh @@ -33,9 +33,9 @@ echo "Starting nodes" i=0 for h in $nodes; do if [ $i -eq `expr $count - 1` ]; then - ssh $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --listen $h:9001 --socket $h$options + ssh $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --socket $h$options else - ssh -f $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --listen $h:9001 --socket $h $options + ssh -f $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --socket $h $options fi i=`expr $i + 1` done diff --git a/ctdb/tests/bench.sh b/ctdb/tests/bench.sh index eca604c2df0..f9430919ea6 100755 --- a/ctdb/tests/bench.sh +++ b/ctdb/tests/bench.sh @@ -15,7 +15,7 @@ done killall -9 ctdb_bench echo "Trying $NUMNODES nodes" for i in `seq 1 $NUMNODES`; do - $VALGRIND bin/ctdb_bench --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* & + $VALGRIND bin/ctdb_bench --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* & done wait diff --git a/ctdb/tests/ctdbd.sh b/ctdb/tests/ctdbd.sh index 1a719e2249d..03897af358d 100755 --- a/ctdb/tests/ctdbd.sh +++ b/ctdb/tests/ctdbd.sh @@ -3,8 +3,8 @@ killall -q ctdbd echo "Starting 2 ctdb daemons" -bin/ctdbd --nlist direct/nodes.txt --listen 127.0.0.2:9001 -bin/ctdbd --nlist direct/nodes.txt --listen 127.0.0.1:9001 +bin/ctdbd --nlist direct/nodes.txt +bin/ctdbd --nlist direct/nodes.txt echo "Testing ping" bin/ctdb_control ping || exit 1 diff --git a/ctdb/tests/fetch.sh b/ctdb/tests/fetch.sh index 9b611013e96..fb384e2935c 100755 --- a/ctdb/tests/fetch.sh +++ b/ctdb/tests/fetch.sh @@ -13,6 +13,6 @@ done killall -9 ctdb_fetch echo "Trying $NUMNODES nodes" for i in `seq 1 $NUMNODES`; do - $VALGRIND bin/ctdb_fetch --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* & + $VALGRIND bin/ctdb_fetch --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* & done wait diff --git a/ctdb/tests/fetch1.sh b/ctdb/tests/fetch1.sh index db584ec0120..0338db4f9fa 100755 --- a/ctdb/tests/fetch1.sh +++ b/ctdb/tests/fetch1.sh @@ -3,5 +3,5 @@ killall -q ctdb_fetch1 echo "Trying node" -bin/ctdb_fetch1 --nlist tests/1node.txt --listen 127.0.0.1:9001 $* +bin/ctdb_fetch1 --nlist tests/1node.txt $* wait diff --git a/ctdb/tests/messaging.sh b/ctdb/tests/messaging.sh index 25f68f3bb6a..07ca2ca5c91 100755 --- a/ctdb/tests/messaging.sh +++ b/ctdb/tests/messaging.sh @@ -17,7 +17,7 @@ done killall -9 ctdb_messaging echo "Trying $NUMNODES nodes" for i in `seq 1 $NUMNODES`; do - $VALGRIND bin/ctdb_messaging --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* & + $VALGRIND bin/ctdb_messaging --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* & done wait diff --git a/ctdb/tests/test.sh b/ctdb/tests/test.sh index f95354a2d79..c243dbd0327 100755 --- a/ctdb/tests/test.sh +++ b/ctdb/tests/test.sh @@ -18,7 +18,7 @@ done killall -9 ctdb_test echo "Trying $NUMNODES nodes" for i in `seq 1 $NUMNODES`; do - $VALGRIND bin/ctdb_test --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* & + $VALGRIND bin/ctdb_test --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* & done wait diff --git a/ctdb/tests/test1.sh b/ctdb/tests/test1.sh index 42256f22f9d..cca46e04c6e 100755 --- a/ctdb/tests/test1.sh +++ b/ctdb/tests/test1.sh @@ -1,9 +1,9 @@ #!/bin/sh echo "Testing daemon mode" -bin/ctdb_test --nlist tests/1node.txt --listen 127.0.0.1:9001 +bin/ctdb_test --nlist tests/1node.txt wait echo "Testing self connect" -bin/ctdb_test --nlist tests/1node.txt --listen 127.0.0.1:9001 --self-connect +bin/ctdb_test --nlist tests/1node.txt --self-connect wait