summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ctdb/tests/src/ctdb_test_stubs.c23
-rwxr-xr-xctdb/tests/tool/stubby.natgwlist.009.sh36
-rwxr-xr-xctdb/tests/tool/stubby.natgwlist.010.sh37
-rw-r--r--ctdb/tools/ctdb.c80
4 files changed, 143 insertions, 33 deletions
diff --git a/ctdb/tests/src/ctdb_test_stubs.c b/ctdb/tests/src/ctdb_test_stubs.c
index 6149b3d334..d36fe81567 100644
--- a/ctdb/tests/src/ctdb_test_stubs.c
+++ b/ctdb/tests/src/ctdb_test_stubs.c
@@ -30,6 +30,10 @@ static struct ctdb_context *ctdb_global;
* -CTDB_CAP_RECMASTER. LVS can be faked on by adding
* CTDB_CAP_LVS.
*/
+
+/* A fake flag that is only supported by some functions */
+#define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
+
void ctdb_test_stubs_read_nodemap(struct ctdb_context *ctdb)
{
char line[1024];
@@ -95,6 +99,12 @@ void ctdb_test_stubs_read_nodemap(struct ctdb_context *ctdb)
capabilities &= ~CTDB_CAP_NATGW;
} else if (strcmp(tok, "CTDB_CAP_LVS") == 0) {
capabilities |= CTDB_CAP_LVS;
+ } else if (strcmp(tok, "TIMEOUT") == 0) {
+ /* This can be done with just a flag
+ * value but it is probably clearer
+ * and less error-prone to fake this
+ * with an explicit token */
+ flags |= NODE_FLAGS_FAKE_TIMEOUT;
}
tok = strtok(NULL, " \t");
}
@@ -550,6 +560,19 @@ int ctdb_ctrl_getcapabilities_stub(struct ctdb_context *ctdb,
struct timeval timeout, uint32_t destnode,
uint32_t *capabilities)
{
+
+ if (ctdb->nodes[destnode]->flags & NODE_FLAGS_FAKE_TIMEOUT) {
+ /* Placeholder for line#, instead of __location__ */
+ DEBUG(DEBUG_ERR,
+ ("__LOCATION__ control timed out."
+ " reqid:1234567890 opcode:80 dstnode:%d\n", destnode));
+ DEBUG(DEBUG_ERR,
+ ("__LOCATION__ ctdb_control_recv failed\n"));
+ DEBUG(DEBUG_ERR,
+ ("__LOCATION__ ctdb_ctrl_getcapabilities_recv failed\n"));
+ return -1;
+ }
+
if (ctdb->nodes[destnode]->flags & NODE_FLAGS_DISCONNECTED) {
DEBUG(DEBUG_ERR,
("ctdb_control error: 'ctdb_control to disconnected node\n"));
diff --git a/ctdb/tests/tool/stubby.natgwlist.009.sh b/ctdb/tests/tool/stubby.natgwlist.009.sh
new file mode 100755
index 0000000000..7534fd220a
--- /dev/null
+++ b/ctdb/tests/tool/stubby.natgwlist.009.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+define_test "3 nodes, all in natgw group, 1 actual time-out"
+
+setup_natgw <<EOF
+192.168.20.41
+192.168.20.42
+192.168.20.43
+EOF
+
+required_result 255 <<EOF
+DATE TIME [PID]: __LOCATION__ control timed out. reqid:1234567890 opcode:80 dstnode:0
+DATE TIME [PID]: __LOCATION__ ctdb_control_recv failed
+DATE TIME [PID]: __LOCATION__ ctdb_ctrl_getcapabilities_recv failed
+DATE TIME [PID]: Unable to get capabilities from node 0
+EOF
+
+simple_test <<EOF
+NODEMAP
+0 192.168.20.41 0x0 TIMEOUT
+1 192.168.20.42 0x0 CURRENT RECMASTER
+2 192.168.20.43 0x0
+
+VNNMAP
+654321
+0
+1
+2
+
+IFACES
+:Name:LinkStatus:References:
+:eth2:1:2:
+:eth1:1:4:
+EOF
diff --git a/ctdb/tests/tool/stubby.natgwlist.010.sh b/ctdb/tests/tool/stubby.natgwlist.010.sh
new file mode 100755
index 0000000000..aaa3161d0b
--- /dev/null
+++ b/ctdb/tests/tool/stubby.natgwlist.010.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+define_test "3 nodes, all in natgw group, 1 potential time-out"
+
+setup_natgw <<EOF
+192.168.20.41
+192.168.20.42
+192.168.20.43
+EOF
+
+required_result 0 <<EOF
+0 192.168.20.41
+Number of nodes:3
+pnn:0 192.168.20.41 OK (THIS NODE)
+pnn:1 192.168.20.42 OK
+pnn:2 192.168.20.43 OK
+EOF
+
+simple_test <<EOF
+NODEMAP
+0 192.168.20.41 0x0 CURRENT RECMASTER
+1 192.168.20.42 0x0
+2 192.168.20.43 0x0 TIMEOUT
+
+VNNMAP
+654321
+0
+1
+2
+
+IFACES
+:Name:LinkStatus:References:
+:eth2:1:2:
+:eth1:1:4:
+EOF
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index 8033fcb7ae..4704726de7 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -1179,7 +1179,8 @@ filter_nodemap_by_addrs(struct ctdb_context *ctdb,
static struct ctdb_node_map *
filter_nodemap_by_capabilities(struct ctdb_context *ctdb,
struct ctdb_node_map *nodemap,
- uint32_t required_capabilities)
+ uint32_t required_capabilities,
+ bool first_only)
{
int i;
uint32_t capabilities;
@@ -1213,6 +1214,9 @@ filter_nodemap_by_capabilities(struct ctdb_context *ctdb,
ret->nodes[ret->num] = nodemap->nodes[i];
ret->num++;
+ if (first_only) {
+ break;
+ }
}
return ret;
@@ -1252,7 +1256,7 @@ static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **a
int i, ret;
struct pnn_node *natgw_nodes = NULL;
struct ctdb_node_map *orig_nodemap=NULL;
- struct ctdb_node_map *cnodemap, *nodemap;
+ struct ctdb_node_map *nodemap;
uint32_t mypnn, pnn;
const char *ip;
@@ -1293,21 +1297,15 @@ static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **a
goto done;
}
- /* Get a nodemap that includes only the nodes with the NATGW
- * capability */
- cnodemap = filter_nodemap_by_capabilities(ctdb, nodemap,
- CTDB_CAP_NATGW);
- if (cnodemap == NULL) {
- ret = -1;
- goto done;
- }
-
ret = 2; /* matches ENOENT */
pnn = -1;
ip = "0.0.0.0";
+ /* For each flag mask... */
for (i = 0; exclude_flags[i] != 0; i++) {
+ /* ... get a nodemap that excludes nodes with with
+ * masked flags... */
struct ctdb_node_map *t =
- filter_nodemap_by_flags(ctdb, cnodemap,
+ filter_nodemap_by_flags(ctdb, nodemap,
exclude_flags[i]);
if (t == NULL) {
/* No memory */
@@ -1315,10 +1313,23 @@ static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **a
goto done;
}
if (t->num > 0) {
- ret = 0;
- pnn = t->nodes[0].pnn;
- ip = ctdb_addr_to_str(&t->nodes[0].addr);
- break;
+ /* ... and find the first node with the NATGW
+ * capability */
+ struct ctdb_node_map *n;
+ n = filter_nodemap_by_capabilities(ctdb, t,
+ CTDB_CAP_NATGW,
+ true);
+ if (n == NULL) {
+ /* No memory */
+ ret = -1;
+ goto done;
+ }
+ if (n->num > 0) {
+ ret = 0;
+ pnn = n->nodes[0].pnn;
+ ip = ctdb_addr_to_str(&n->nodes[0].addr);
+ break;
+ }
}
talloc_free(t);
}
@@ -3569,7 +3580,7 @@ static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
}
nodemap = filter_nodemap_by_capabilities(ctdb, orig_nodemap,
- CTDB_CAP_LVS);
+ CTDB_CAP_LVS, false);
if (nodemap == NULL) {
/* No memory */
ret = -1;
@@ -3609,26 +3620,17 @@ done:
static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
{
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
- struct ctdb_node_map *orig_nodemap=NULL;
- struct ctdb_node_map *nodemap;
+ struct ctdb_node_map *nodemap=NULL;
int i, ret;
ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn,
- tmp_ctx, &orig_nodemap);
+ tmp_ctx, &nodemap);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
talloc_free(tmp_ctx);
return -1;
}
- nodemap = filter_nodemap_by_capabilities(ctdb, orig_nodemap,
- CTDB_CAP_LVS);
- if (nodemap == NULL) {
- /* No memory */
- ret = -1;
- goto done;
- }
-
for (i = 0; lvs_exclude_flags[i] != 0; i++) {
struct ctdb_node_map *t =
filter_nodemap_by_flags(ctdb, nodemap,
@@ -3639,11 +3641,23 @@ static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **a
goto done;
}
if (t->num > 0) {
- ret = 0;
- printf(options.machinereadable ?
- "%d\n" : "Node %d is LVS master\n",
- t->nodes[0].pnn);
- goto done;
+ struct ctdb_node_map *n;
+ n = filter_nodemap_by_capabilities(ctdb,
+ t,
+ CTDB_CAP_LVS,
+ true);
+ if (n == NULL) {
+ /* No memory */
+ ret = -1;
+ goto done;
+ }
+ if (n->num > 0) {
+ ret = 0;
+ printf(options.machinereadable ?
+ "%d\n" : "Node %d is LVS master\n",
+ n->nodes[0].pnn);
+ goto done;
+ }
}
talloc_free(t);
}