ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
if (!strcmp(name, db_name)) {
if (persistent) {
- *persistent = dbmap->dbs[i].persistent;
+ *persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
}
return 0;
}
/* or if we still can not find any */
if (i == nodemap->num) {
printf("-1 0.0.0.0\n");
+ ret = 2; /* matches ENOENT */
}
}
!!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
}
- return 0;
+ return ret;
}
/*
static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
{
uint32_t pnn;
+ int ret, retries = 0;
ctdb_sock_addr addr;
if (argc < 2) {
return -1;
}
- if (move_ip(ctdb, &addr, pnn) != 0) {
- DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
+ do {
+ ret = move_ip(ctdb, &addr, pnn);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,("Failed to move ip to node %d. Wait 3 second and try again.\n", pnn));
+ sleep(3);
+ retries++;
+ }
+ } while (retries < 5 && ret != 0);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,("Failed to move ip to node %d. Giving up.\n", pnn));
return -1;
}
static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
{
int i, ret;
- int len;
- uint32_t pnn;
+ int len, retries = 0;
unsigned mask;
ctdb_sock_addr addr;
struct ctdb_control_ip_iface *pub;
return -1;
}
- ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
+ /* read the public ip list from the node */
+ ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
+ DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", options.pnn));
talloc_free(tmp_ctx);
- return ret;
+ return -1;
}
-
-
- /* check if some other node is already serving this ip, if not,
- * we will claim it
- */
for (i=0;i<ips->num;i++) {
if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
- break;
+ DEBUG(DEBUG_ERR,("Can not add ip to node. Node already hosts this ip\n"));
+ return 0;
}
}
+
+
+ /* Dont timeout. This command waits for an ip reallocation
+ which sometimes can take wuite a while if there has
+ been a recent recovery
+ */
+ alarm(0);
+
len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
pub = talloc_size(tmp_ctx, len);
CTDB_NO_MEMORY(ctdb, pub);
pub->len = strlen(argv[1])+1;
memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
- ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
+ do {
+ ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u. Wait 3 seconds and try again.\n", options.pnn));
+ sleep(3);
+ retries++;
+ }
+ } while (retries < 5 && ret != 0);
if (ret != 0) {
- DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
+ DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u. Giving up.\n", options.pnn));
talloc_free(tmp_ctx);
return ret;
}
- if (i == ips->num) {
- /* no one has this ip so we claim it */
- pnn = options.pnn;
- } else {
- pnn = ips->ips[i].pnn;
- }
-
- if (move_ip(ctdb, &addr, pnn) != 0) {
- DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
- return -1;
- }
-
- ret = control_ipreallocate(ctdb, argc, argv);
+ do {
+ ret = control_ipreallocate(ctdb, argc, argv);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u. Wait 3 seconds and try again.\n", options.pnn));
+ sleep(3);
+ retries++;
+ }
+ } while (retries < 5 && ret != 0);
if (ret != 0) {
- DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
+ DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u. Giving up.\n", options.pnn));
+ talloc_free(tmp_ctx);
return ret;
}
static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
{
int i, ret;
+ int retries = 0;
ctdb_sock_addr addr;
struct ctdb_control_ip_iface pub;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
if (ips->ips[i].pnn == options.pnn) {
ret = find_other_host_for_public_ip(ctdb, &addr);
if (ret != -1) {
- if (move_ip(ctdb, &addr, ret) != 0) {
- DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
+ do {
+ ret = move_ip(ctdb, &addr, ret);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,("Failed to move ip to node %d. Wait 3 seconds and try again.\n", options.pnn));
+ sleep(3);
+ retries++;
+ }
+ } while (retries < 5 && ret != 0);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,("Failed to move ip to node %d. Giving up.\n", options.pnn));
return -1;
}
}
return 0;
}
+struct cattdb_data {
+ struct ctdb_context *ctdb;
+ uint32_t count;
+};
+
+static int cattdb_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ struct cattdb_data *d = private_data;
+
+ d->count++;
+
+ return ctdb_dumpdb_record(d->ctdb, key, data, stdout);
+}
+
+/*
+ cat the local tdb database using same format as catdb
+ */
+static int control_cattdb(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ const char *db_name;
+ struct ctdb_db_context *ctdb_db;
+ struct cattdb_data d;
+ bool persistent;
+
+ if (argc < 1) {
+ usage();
+ }
+
+ db_name = argv[0];
+
+
+ if (db_exists(ctdb, db_name, &persistent)) {
+ DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
+ return -1;
+ }
+
+ ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
+
+ if (ctdb_db == NULL) {
+ DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
+ return -1;
+ }
+
+ /* traverse the local tdb */
+ d.count = 0;
+ d.ctdb = ctdb;
+ if (tdb_traverse_read(ctdb_db->ltdb->tdb, cattdb_traverse, &d) == -1) {
+ printf("Failed to cattdb data\n");
+ exit(10);
+ }
+ talloc_free(ctdb_db);
+
+ printf("Dumped %d records\n", d.count);
+ return 0;
+}
+
/*
display the content of a database key
*/
struct ctdb_record_handle *h;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
TDB_DATA key, data;
+ bool persistent;
if (argc < 2) {
usage();
db_name = argv[0];
- if (db_exists(ctdb, db_name)) {
+ if (db_exists(ctdb, db_name, &persistent)) {
DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
return -1;
}
- ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
+ ctdb_db = ctdb_attach(ctdb, db_name, persistent, 0);
if (ctdb_db == NULL) {
DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
struct ctdb_record_handle *h;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
TDB_DATA key, data;
+ bool persistent;
if (argc < 3) {
usage();
db_name = argv[0];
- if (db_exists(ctdb, db_name)) {
+ if (db_exists(ctdb, db_name, &persistent)) {
DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
return -1;
}
- ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
+ ctdb_db = ctdb_attach(ctdb, db_name, persistent, 0);
if (ctdb_db == NULL) {
DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
return 0;
}
+/*
+ check if a service is bound to a port or not
+ */
+static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ int s, ret;
+ unsigned v;
+ int port;
+ struct sockaddr_in sin;
+
+ if (argc != 1) {
+ printf("Use: ctdb chktcport <port>\n");
+ return EINVAL;
+ }
+
+ port = atoi(argv[0]);
+
+ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s == -1) {
+ printf("Failed to open local socket\n");
+ return errno;
+ }
+
+ v = fcntl(s, F_GETFL, 0);
+ fcntl(s, F_SETFL, v | O_NONBLOCK);
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = PF_INET;
+ sin.sin_port = htons(port);
+ ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
+ close(s);
+ if (ret == -1) {
+ printf("Failed to bind to local socket: %d %s\n", errno, strerror(errno));
+ return errno;
+ }
+
+ return 0;
+}
+
+
+
static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
TDB_DATA data, void *private_data)
{
}
if(options.machinereadable){
- printf(":ID:Name:Path:Persistent:Unhealthy:\n");
+ printf(":ID:Name:Path:Persistent:Unhealthy:ReadOnly:\n");
for(i=0;i<dbmap->num;i++){
const char *path;
const char *name;
const char *health;
bool persistent;
+ bool readonly;
ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
dbmap->dbs[i].dbid, ctdb, &path);
dbmap->dbs[i].dbid, ctdb, &name);
ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
dbmap->dbs[i].dbid, ctdb, &health);
- persistent = dbmap->dbs[i].persistent;
- printf(":0x%08X:%s:%s:%d:%d:\n",
+ persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+ readonly = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+ printf(":0x%08X:%s:%s:%d:%d:%d:\n",
dbmap->dbs[i].dbid, name, path,
- !!(persistent), !!(health));
+ !!(persistent), !!(health), !!(readonly));
}
return 0;
}
const char *name;
const char *health;
bool persistent;
+ bool readonly;
ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
- persistent = dbmap->dbs[i].persistent;
- printf("dbid:0x%08x name:%s path:%s%s%s\n",
+ persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+ readonly = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+ printf("dbid:0x%08x name:%s path:%s%s%s%s\n",
dbmap->dbs[i].dbid, name, path,
persistent?" PERSISTENT":"",
+ readonly?" READONLY":"",
health?" UNHEALTHY":"");
}
const char *name;
const char *health;
bool persistent;
+ bool readonly;
ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
if (strcmp(name, db_name) != 0) {
ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
- persistent = dbmap->dbs[i].persistent;
- printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
+ persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
+ readonly = dbmap->dbs[i].flags & CTDB_DB_FLAGS_READONLY;
+ printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nREADONLY: %s\nHEALTH: %s\n",
dbmap->dbs[i].dbid, name, path,
persistent?"yes":"no",
+ readonly?"yes":"no",
health?health:"OK");
return 0;
}
allow_unhealthy));
}
- ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
+ ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT, 0);
if (ctdb_db == NULL) {
DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
talloc_free(tmp_ctx);
dbhdr.version = DB_VERSION;
dbhdr.timestamp = time(NULL);
- dbhdr.persistent = dbmap->dbs[i].persistent;
+ dbhdr.persistent = dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT;
dbhdr.size = bd->len;
if (strlen(argv[0]) >= MAX_DB_NAME) {
DEBUG(DEBUG_ERR,("Too long dbname\n"));
DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
}
}
+
+ DEBUG(DEBUG_ERR,("Database acked up to %s\n", argv[1]));
+
talloc_free(tmp_ctx);
return status;
}
return -1;
}
- ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
+ ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].flags & CTDB_DB_FLAGS_PERSISTENT, 0);
if (ctdb_db == NULL) {
DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
argv[0]));
return -1;
}
+ DEBUG(DEBUG_ERR, ("Database wiped.\n"));
+
talloc_free(tmp_ctx);
return 0;
}
{ "getdbmap", control_getdbmap, true, false, "show the database map" },
{ "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
{ "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
+ { "cattdb", control_cattdb, true, false, "dump a database" , "<dbname>"},
{ "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
{ "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
{ "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
{ "tfetch", control_tfetch, false, true, "fetch a record from a [c]tdb-file", "<tdb-file> <key> [<file>]" },
{ "readkey", control_readkey, true, false, "read the content off a database key", "<tdb-file> <key>" },
{ "writekey", control_writekey, true, false, "write to a database key", "<tdb-file> <key> <value>" },
+ { "checktcpport", control_chktcpport, false, true, "check if a service is bound to a specific tcp port or not", "<port>" },
};
/*