ctdb-tools/ctdb: Detach databases only if all nodes disallow client access
authorAmitay Isaacs <amitay@gmail.com>
Tue, 15 Apr 2014 02:27:44 +0000 (12:27 +1000)
committerMichael Adam <obnox@samba.org>
Wed, 23 Apr 2014 12:49:07 +0000 (14:49 +0200)
This makes sure that AllowClientDBAttach is set to 0 before detaching any
databases.

If someone enables the tunable between checking of tunable and actual
detaching of databases, then they deserve what they get. :-)

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Michael Adam <obnox@samba.org>
ctdb/doc/ctdb.1.xml
ctdb/tools/ctdb.c

index 95a67dbeeda709086eba4cfbf7f01d822b10e4b7..433e65018afb2fb845a385b6595ffc769c27f26f 100644 (file)
@@ -1576,6 +1576,10 @@ HEALTH: NO-HEALTHY-NODES - ERROR - Backup of corrupted TDB in '/var/ctdb/persist
        the cluster.  This command should only be used when none of the
        specified database(s) are in use.
       </para>
+      <para>
+       All nodes should be active and tunable AllowClientDBAccess should
+       be disabled on all nodes before detaching databases.
+      </para>
     </refsect2>
 
     <refsect2>
index 74cf321fa260fac29b428d011f4d1f1a92c8afca..4afb3e7af7b5b1afd675d5096974bf63f7b65a35 100644 (file)
@@ -5194,6 +5194,9 @@ static int control_detach(struct ctdb_context *ctdb, int argc,
        uint32_t db_id;
        uint8_t flags;
        int ret, i, status = 0;
+       struct ctdb_node_map *nodemap = NULL;
+       TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+       uint32_t recmode;
 
        if (argc < 1) {
                usage();
@@ -5201,6 +5204,67 @@ static int control_detach(struct ctdb_context *ctdb, int argc,
 
        assert_single_node_only();
 
+       ret = ctdb_ctrl_getrecmode(ctdb, tmp_ctx, TIMELIMIT(), options.pnn,
+                                   &recmode);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, ("Database cannot be detached "
+                                 "when recovery is active\n"));
+               talloc_free(tmp_ctx);
+               return -1;
+       }
+
+       ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, 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;
+       }
+
+       for (i=0; i<nodemap->num; i++) {
+               uint32_t value;
+
+               if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
+                       continue;
+               }
+
+               if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
+                       continue;
+               }
+
+               if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
+                       DEBUG(DEBUG_ERR, ("Database cannot be detached on "
+                                         "inactive (stopped or banned) node "
+                                         "%u\n", nodemap->nodes[i].pnn));
+                       talloc_free(tmp_ctx);
+                       return -1;
+               }
+
+               ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(),
+                                           nodemap->nodes[i].pnn,
+                                           "AllowClientDBAttach",
+                                           &value);
+               if (ret != 0) {
+                       DEBUG(DEBUG_ERR, ("Unable to get tunable "
+                                         "AllowClientDBAttach from node %u\n",
+                                          nodemap->nodes[i].pnn));
+                       talloc_free(tmp_ctx);
+                       return -1;
+               }
+
+               if (value == 1) {
+                       DEBUG(DEBUG_ERR, ("Database access is still active on "
+                                         "node %u. Set AllowClientDBAttach=0 "
+                                         "on all nodes.\n",
+                                         nodemap->nodes[i].pnn));
+                       talloc_free(tmp_ctx);
+                       return -1;
+               }
+       }
+
+       talloc_free(tmp_ctx);
+
        for (i=0; i<argc; i++) {
                if (!db_exists(ctdb, argv[i], &db_id, NULL, &flags)) {
                        continue;