2
Copyright (c) 2011-2012 Red Hat, Inc. <http://www.redhat.com>
3
This file is part of GlusterFS.
5
This file is licensed to you under your choice of the GNU Lesser
6
General Public License, version 3 or any later version (LGPLv3 or
7
later), or the GNU General Public License, version 2 (GPLv2), in all
8
cases as published by the Free Software Foundation.
10
#include "glusterd-op-sm.h"
11
#include "glusterd-geo-rep.h"
12
#include "glusterd-store.h"
13
#include "glusterd-utils.h"
14
#include "glusterd-volgen.h"
15
#include "glusterd-svc-helper.h"
16
#include <glusterfs/run.h>
17
#include <glusterfs/syscall.h>
18
#include "glusterd-messages.h"
23
dict_get_param(dict_t *dict, char *key, char **param);
25
struct gsync_config_opt_vals_ gsync_confopt_vals[] = {
27
.op_name = "change_detector",
29
.case_sensitive = _gf_true,
30
.values = {"xsync", "changelog"},
32
{.op_name = "special_sync_mode",
34
.case_sensitive = _gf_true,
35
.values = {"partial", "recover"}},
36
{.op_name = "log-level",
38
.case_sensitive = _gf_false,
39
.values = {"critical", "error", "warning", "info", "debug"}},
40
{.op_name = "use-tarssh",
42
.case_sensitive = _gf_false,
43
.values = {"true", "false", "0", "1", "yes", "no"}},
44
{.op_name = "ignore_deletes",
46
.case_sensitive = _gf_false,
47
.values = {"true", "false", "0", "1", "yes", "no"}},
48
{.op_name = "use_meta_volume",
50
.case_sensitive = _gf_false,
51
.values = {"true", "false", "0", "1", "yes", "no"}},
52
{.op_name = "use-meta-volume",
54
.case_sensitive = _gf_false,
55
.values = {"true", "false", "0", "1", "yes", "no"}},
61
static char *gsync_reserved_opts[] = {
62
"gluster-command", "pid-file", "state-file", "session-owner",
63
"state-socket-unencoded", "socketdir", "local-id", "local-path",
64
"secondary-id", NULL};
66
static char *gsync_no_restart_opts[] = {"checkpoint", "log_rsync_performance",
67
"log-rsync-performance", NULL};
70
set_gsyncd_inet6_arg(runner_t *runner)
75
ret = dict_get_str(THIS->options, "transport.address-family", &af);
77
runner_argprintf(runner, "--%s", af);
81
__glusterd_handle_sys_exec(rpcsvc_request_t *req)
85
gf_cli_req cli_req = {
88
glusterd_op_t cli_op = GD_OP_SYS_EXEC;
89
glusterd_conf_t *priv = NULL;
90
char *host_uuid = NULL;
94
xlator_t *this = THIS;
101
ret = xdr_to_generic(req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
103
req->rpc_err = GARBAGE_ARGS;
104
snprintf(err_str, sizeof(err_str), "Garbage args received");
105
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_GARBAGE_ARGS, NULL);
109
if (cli_req.dict.dict_len) {
112
gf_smsg(THIS->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL,
117
ret = dict_unserialize(cli_req.dict.dict_val, cli_req.dict.dict_len,
120
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_UNSERIALIZE_FAIL,
122
"unserialize req-buffer to dictionary");
123
snprintf(err_str, sizeof(err_str),
128
dict->extra_stdfree = cli_req.dict.dict_val;
131
host_uuid = gf_strdup(uuid_utoa(MY_UUID));
132
if (host_uuid == NULL) {
133
snprintf(err_str, sizeof(err_str),
135
"the uuid of local glusterd");
136
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_UUID_GET_FAIL,
142
ret = dict_set_dynstr(dict, "host-uuid", host_uuid);
144
gf_smsg(this->name, GF_LOG_ERROR, -ret, GD_MSG_DICT_SET_FAILED,
145
"Key=host-uuid", NULL);
150
ret = glusterd_op_begin_synctask(req, cli_op, dict);
154
if (err_str[0] == '\0')
155
snprintf(err_str, sizeof(err_str), "Operation failed");
156
ret = glusterd_op_send_cli_response(cli_op, ret, 0, req, dict, err_str);
162
__glusterd_handle_copy_file(rpcsvc_request_t *req)
166
gf_cli_req cli_req = {
169
glusterd_op_t cli_op = GD_OP_COPY_FILE;
170
glusterd_conf_t *priv = NULL;
171
char *host_uuid = NULL;
175
xlator_t *this = THIS;
179
priv = this->private;
182
ret = xdr_to_generic(req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
184
req->rpc_err = GARBAGE_ARGS;
185
snprintf(err_str, sizeof(err_str), "Garbage args received");
186
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_GARBAGE_ARGS, NULL);
190
if (cli_req.dict.dict_len) {
193
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL,
198
ret = dict_unserialize(cli_req.dict.dict_val, cli_req.dict.dict_len,
201
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_UNSERIALIZE_FAIL,
203
"unserialize req-buffer to dictionary");
204
snprintf(err_str, sizeof(err_str),
209
dict->extra_stdfree = cli_req.dict.dict_val;
212
host_uuid = gf_strdup(uuid_utoa(MY_UUID));
213
if (host_uuid == NULL) {
214
snprintf(err_str, sizeof(err_str),
216
"the uuid of local glusterd");
217
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_UUID_GET_FAIL,
223
ret = dict_set_dynstr(dict, "host-uuid", host_uuid);
228
ret = glusterd_op_begin_synctask(req, cli_op, dict);
232
if (err_str[0] == '\0')
233
snprintf(err_str, sizeof(err_str), "Operation failed");
234
ret = glusterd_op_send_cli_response(cli_op, ret, 0, req, dict, err_str);
240
__glusterd_handle_gsync_set(rpcsvc_request_t *req)
244
gf_cli_req cli_req = {
247
glusterd_op_t cli_op = GD_OP_GSYNC_SET;
248
char *primary = NULL;
249
char *secondary = NULL;
250
char operation[64] = {
254
glusterd_conf_t *priv = NULL;
255
char *host_uuid = NULL;
259
xlator_t *this = THIS;
263
priv = this->private;
266
ret = xdr_to_generic(req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
268
req->rpc_err = GARBAGE_ARGS;
269
snprintf(err_str, sizeof(err_str), "Garbage args received");
270
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_GARBAGE_ARGS, NULL);
274
if (cli_req.dict.dict_len) {
277
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL,
282
ret = dict_unserialize(cli_req.dict.dict_val, cli_req.dict.dict_len,
285
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_UNSERIALIZE_FAIL,
287
"unserialize req-buffer to dictionary");
288
snprintf(err_str, sizeof(err_str),
293
dict->extra_stdfree = cli_req.dict.dict_val;
296
host_uuid = gf_strdup(uuid_utoa(MY_UUID));
297
if (host_uuid == NULL) {
298
snprintf(err_str, sizeof(err_str),
300
"the uuid of local glusterd");
301
gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_UUID_GET_FAIL,
306
ret = dict_set_dynstr(dict, "host-uuid", host_uuid);
311
ret = dict_get_str(dict, "primary", &primary);
313
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DICT_GET_FAILED,
314
"primary not found, while handling " GEOREP " options");
315
primary = "(No Primary)";
318
ret = dict_get_str(dict, "secondary", &secondary);
320
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DICT_GET_FAILED,
321
"secondary not found, while handling " GEOREP " options");
322
secondary = "(No Secondary)";
325
ret = dict_get_int32(dict, "type", &type);
327
snprintf(err_str, sizeof(err_str),
328
"Command type not found "
329
"while handling " GEOREP " options");
330
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
336
case GF_GSYNC_OPTION_TYPE_CREATE:
337
snprintf(operation, sizeof(operation), "create");
338
cli_op = GD_OP_GSYNC_CREATE;
341
case GF_GSYNC_OPTION_TYPE_START:
342
snprintf(operation, sizeof(operation), "start");
345
case GF_GSYNC_OPTION_TYPE_STOP:
346
snprintf(operation, sizeof(operation), "stop");
349
case GF_GSYNC_OPTION_TYPE_PAUSE:
350
snprintf(operation, sizeof(operation), "pause");
353
case GF_GSYNC_OPTION_TYPE_RESUME:
354
snprintf(operation, sizeof(operation), "resume");
357
case GF_GSYNC_OPTION_TYPE_CONFIG:
358
snprintf(operation, sizeof(operation), "config");
361
case GF_GSYNC_OPTION_TYPE_STATUS:
362
snprintf(operation, sizeof(operation), "status");
366
ret = glusterd_op_begin_synctask(req, cli_op, dict);
370
if (err_str[0] == '\0')
371
snprintf(err_str, sizeof(err_str), "Operation failed");
372
ret = glusterd_op_send_cli_response(cli_op, ret, 0, req, dict, err_str);
378
glusterd_handle_sys_exec(rpcsvc_request_t *req)
380
return glusterd_big_locked_handler(req, __glusterd_handle_sys_exec);
384
glusterd_handle_copy_file(rpcsvc_request_t *req)
386
return glusterd_big_locked_handler(req, __glusterd_handle_copy_file);
390
glusterd_handle_gsync_set(rpcsvc_request_t *req)
392
return glusterd_big_locked_handler(req, __glusterd_handle_gsync_set);
397
* glusterd_urltransform* internal API
402
glusterd_urltransform_init(runner_t *runner, const char *transname)
405
runner_add_arg(runner, GSYNCD_PREFIX "/gsyncd");
406
set_gsyncd_inet6_arg(runner);
407
runner_argprintf(runner, "--%s-url", transname);
411
glusterd_urltransform_add(runner_t *runner, const char *url)
413
runner_add_arg(runner, url);
416
/* Helper routine to terminate just before secondary_voluuid */
418
parse_secondary_url(char *sec_url, char **secondary)
421
xlator_t *this = THIS;
427
* primary_node_uuid:ssh://secondary_host::secondary_vol:secondary_voluuid
429
*secondary = strchr(sec_url, ':');
435
/* To terminate at : before secondary volume uuid */
436
tmp = strstr(*secondary, "::");
441
tmp = strchr(tmp, ':');
443
gf_msg_debug(this->name, 0, "old secondary: %s!", *secondary);
448
gf_msg_debug(this->name, 0, "parsed secondary: %s!", *secondary);
454
_glusterd_urltransform_add_iter(dict_t *dict, char *key, data_t *value,
457
runner_t *runner = (runner_t *)data;
458
char sec_url[VOLINFO_SECONDARY_URL_MAX] = {0};
459
char *secondary = NULL;
460
xlator_t *this = THIS;
463
gf_msg_debug(this->name, 0, "value->data %s", value->data);
465
if (snprintf(sec_url, sizeof(sec_url), "%s", value->data) >=
467
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
468
"Error in copying secondary: %s!", value->data);
472
ret = parse_secondary_url(sec_url, &secondary);
474
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
475
"Error in parsing secondary: %s!", value->data);
479
runner_add_arg(runner, secondary);
486
glusterd_urltransform_free(char **linearr, unsigned n)
497
glusterd_urltransform(runner_t *runner, char ***linearrp)
499
char **linearr = NULL;
501
unsigned arr_len = 32;
502
unsigned arr_idx = 0;
503
gf_boolean_t error = _gf_false;
504
xlator_t *this = THIS;
506
linearr = GF_CALLOC(arr_len, sizeof(char *), gf_gld_mt_linearr);
512
runner_redir(runner, STDOUT_FILENO, RUN_PIPE);
513
if (runner_start(runner) != 0) {
514
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SPAWNING_CHILD_FAILED,
515
"spawning child failed");
524
line = GF_MALLOC(1024, gf_gld_mt_linebuf);
530
if (fgets(line, 1024, runner_chio(runner, STDOUT_FILENO)) == NULL) {
536
if (len == 0 || line[len - 1] != '\n') {
541
line[len - 1] = '\0';
543
if (arr_idx == arr_len) {
546
p = GF_REALLOC(linearr, arr_len);
554
linearr[arr_idx] = line;
561
/* XXX chpid field is not exported by run API
562
* but runner_end() does not abort the invoked
563
* process (ie. it might block in waitpid(2))
564
* so we resort to a manual kill a the private field
566
if (error && runner->chpid > 0)
567
kill(runner->chpid, SIGKILL);
569
if (runner_end(runner) != 0)
573
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_READ_CHILD_DATA_FAILED,
574
"reading data from child failed");
575
glusterd_urltransform_free(linearr, arr_idx);
584
glusterd_urltransform_single(const char *url, const char *transname,
591
glusterd_urltransform_init(&runner, transname);
592
glusterd_urltransform_add(&runner, url);
593
return glusterd_urltransform(&runner, linearrp);
602
struct secondary_vol_config {
603
char old_sechost[_POSIX_HOST_NAME_MAX + 1];
604
char old_secuser[LOGIN_NAME_MAX];
606
char secondary_voluuid[UUID_CANONICAL_FORM_LEN + 1];
610
_dict_mark_atindex(dict_t *dict, char *key, data_t *value, void *data)
612
struct dictidxmark *dim = data;
614
if (dim->isrch == dim->ithis)
622
dict_get_by_index(dict_t *dict, unsigned i)
624
struct dictidxmark dim = {
629
dict_foreach(dict, _dict_mark_atindex, &dim);
635
glusterd_get_secondary(glusterd_volinfo_t *vol, const char *secondaryurl,
643
char **linearr = NULL;
646
glusterd_urltransform_init(&runner, "canonicalize");
647
ret = dict_foreach(vol->gsync_secondaries, _glusterd_urltransform_add_iter,
652
glusterd_urltransform_add(&runner, secondaryurl);
654
n = glusterd_urltransform(&runner, &linearr);
658
for (i = 0; i < n - 1; i++) {
659
if (strcmp(linearr[i], linearr[n - 1]) == 0)
662
glusterd_urltransform_free(linearr, n);
665
*secondarykey = dict_get_by_index(vol->gsync_secondaries, i);
673
glusterd_query_extutil_generic(char *resbuf, size_t blen, runner_t *runner,
675
int (*fcbk)(char *resbuf, size_t blen, FILE *fp,
679
xlator_t *this = THIS;
681
runner_redir(runner, STDOUT_FILENO, RUN_PIPE);
682
if (runner_start(runner) != 0) {
683
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SPAWNING_CHILD_FAILED,
684
"spawning child failed");
689
ret = fcbk(resbuf, blen, runner_chio(runner, STDOUT_FILENO), data);
691
ret |= runner_end(runner);
693
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_READ_CHILD_DATA_FAILED,
694
"reading data from child failed");
700
_fcbk_singleline(char *resbuf, size_t blen, FILE *fp, void *data)
705
ptr = fgets(resbuf, blen, fp);
707
size_t len = strlen(resbuf);
708
if (len && resbuf[len - 1] == '\n')
709
resbuf[len - 1] = '\0'; // strip off \n
712
return errno ? -1 : 0;
716
glusterd_query_extutil(char *resbuf, runner_t *runner)
718
return glusterd_query_extutil_generic(resbuf, PATH_MAX, runner, NULL,
723
glusterd_get_secondary_voluuid(char *secondary_host, char *secondary_vol,
729
glusterd_conf_t *priv = NULL;
730
xlator_t *this = THIS;
733
priv = this->private;
734
GF_VALIDATE_OR_GOTO(this->name, priv, out);
737
runner_add_arg(&runner, GSYNCD_PREFIX "/gsyncd");
738
set_gsyncd_inet6_arg(&runner);
739
runner_add_arg(&runner, "--secondaryvoluuid-get");
740
runner_argprintf(&runner, "%s::%s", secondary_host, secondary_vol);
742
synclock_unlock(&priv->big_lock);
743
ret = glusterd_query_extutil(vol_uuid, &runner);
744
synclock_lock(&priv->big_lock);
751
_fcbk_conftodict(char *resbuf, size_t blen, FILE *fp, void *data)
759
ptr = fgets(resbuf, blen - 2, fp);
762
v = resbuf + strlen(resbuf) - 1;
764
/* strip trailing space */
767
/* skip empty line */
769
v = strchr(resbuf, ':');
778
if (dict_set_dynstr(dict, resbuf, v) != 0) {
784
return errno ? -1 : 0;
788
glusterd_gsync_get_config(char *primary, char *secondary, char *conf_path,
791
/* key + value, where value must be able to accommodate a path */
792
char resbuf[256 + PATH_MAX] = {
800
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "-c", NULL);
801
runner_argprintf(&runner, "%s", conf_path);
802
set_gsyncd_inet6_arg(&runner);
803
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
804
runner_argprintf(&runner, ":%s", primary);
805
runner_add_args(&runner, secondary, "--config-get-all", NULL);
807
return glusterd_query_extutil_generic(resbuf, sizeof(resbuf), &runner, dict,
812
_fcbk_statustostruct(char *resbuf, size_t blen, FILE *fp, void *data)
817
gf_gsync_status_t *sts_val = NULL;
820
sts_val = (gf_gsync_status_t *)data;
824
ptr = fgets(resbuf, blen - 2, fp);
828
v = resbuf + strlen(resbuf) - 1;
830
/* strip trailing space */
833
/* skip empty line */
835
v = strchr(resbuf, ':');
845
k = gf_strdup(resbuf);
851
if (strcmp(k, "worker_status") == 0) {
852
len = min(strlen(v), (sizeof(sts_val->worker_status) - 1));
853
memcpy(sts_val->worker_status, v, len);
854
sts_val->worker_status[len] = '\0';
855
} else if (strcmp(k, "secondary_node") == 0) {
856
len = min(strlen(v), (sizeof(sts_val->secondary_node) - 1));
857
memcpy(sts_val->secondary_node, v, len);
858
sts_val->secondary_node[len] = '\0';
859
} else if (strcmp(k, "crawl_status") == 0) {
860
len = min(strlen(v), (sizeof(sts_val->crawl_status) - 1));
861
memcpy(sts_val->crawl_status, v, len);
862
sts_val->crawl_status[len] = '\0';
863
} else if (strcmp(k, "last_synced") == 0) {
864
len = min(strlen(v), (sizeof(sts_val->last_synced) - 1));
865
memcpy(sts_val->last_synced, v, len);
866
sts_val->last_synced[len] = '\0';
867
} else if (strcmp(k, "last_synced_utc") == 0) {
868
len = min(strlen(v), (sizeof(sts_val->last_synced_utc) - 1));
869
memcpy(sts_val->last_synced_utc, v, len);
870
sts_val->last_synced_utc[len] = '\0';
871
} else if (strcmp(k, "entry") == 0) {
872
len = min(strlen(v), (sizeof(sts_val->entry) - 1));
873
memcpy(sts_val->entry, v, len);
874
sts_val->entry[len] = '\0';
875
} else if (strcmp(k, "data") == 0) {
876
len = min(strlen(v), (sizeof(sts_val->data) - 1));
877
memcpy(sts_val->data, v, len);
878
sts_val->data[len] = '\0';
879
} else if (strcmp(k, "meta") == 0) {
880
len = min(strlen(v), (sizeof(sts_val->meta) - 1));
881
memcpy(sts_val->meta, v, len);
882
sts_val->meta[len] = '\0';
883
} else if (strcmp(k, "failures") == 0) {
884
len = min(strlen(v), (sizeof(sts_val->failures) - 1));
885
memcpy(sts_val->failures, v, len);
886
sts_val->failures[len] = '\0';
887
} else if (strcmp(k, "checkpoint_time") == 0) {
888
len = min(strlen(v), (sizeof(sts_val->checkpoint_time) - 1));
889
memcpy(sts_val->checkpoint_time, v, len);
890
sts_val->checkpoint_time[len] = '\0';
891
} else if (strcmp(k, "checkpoint_time_utc") == 0) {
892
len = min(strlen(v), (sizeof(sts_val->checkpoint_time_utc) - 1));
893
memcpy(sts_val->checkpoint_time_utc, v, len);
894
sts_val->checkpoint_time_utc[len] = '\0';
895
} else if (strcmp(k, "checkpoint_completed") == 0) {
896
len = min(strlen(v), (sizeof(sts_val->checkpoint_completed) - 1));
897
memcpy(sts_val->checkpoint_completed, v, len);
898
sts_val->checkpoint_completed[len] = '\0';
899
} else if (strcmp(k, "checkpoint_completion_time") == 0) {
901
(sizeof(sts_val->checkpoint_completion_time) - 1));
902
memcpy(sts_val->checkpoint_completion_time, v, len);
903
sts_val->checkpoint_completion_time[len] = '\0';
904
} else if (strcmp(k, "checkpoint_completion_time_utc") == 0) {
906
(sizeof(sts_val->checkpoint_completion_time_utc) - 1));
907
memcpy(sts_val->checkpoint_completion_time_utc, v, len);
908
sts_val->checkpoint_completion_time_utc[len] = '\0';
914
return errno ? -1 : 0;
918
glusterd_gsync_get_status(char *primary, char *secondary, char *conf_path,
919
char *brick_path, gf_gsync_status_t *sts_val)
921
/* key + value, where value must be able to accommodate a path */
922
char resbuf[256 + PATH_MAX] = {
930
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "-c", NULL);
931
runner_argprintf(&runner, "%s", conf_path);
932
set_gsyncd_inet6_arg(&runner);
933
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
934
runner_argprintf(&runner, ":%s", primary);
935
runner_add_args(&runner, secondary, "--status-get", NULL);
936
runner_add_args(&runner, "--path", brick_path, NULL);
938
return glusterd_query_extutil_generic(resbuf, sizeof(resbuf), &runner,
939
sts_val, _fcbk_statustostruct);
943
glusterd_gsync_get_param_file(char *prmfile, const char *param, char *primary,
944
char *secondary, char *conf_path)
951
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "-c", NULL);
952
runner_argprintf(&runner, "%s", conf_path);
953
set_gsyncd_inet6_arg(&runner);
954
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
955
runner_argprintf(&runner, ":%s", primary);
956
runner_add_args(&runner, secondary, "--config-get", NULL);
957
runner_argprintf(&runner, "%s-file", param);
959
return glusterd_query_extutil(prmfile, &runner);
963
gsyncd_getpidfile(char *primary, char *secondary, char *pidfile,
964
char *conf_path, gf_boolean_t *is_template_in_use)
966
char temp_conf_path[PATH_MAX] = "";
967
char *working_conf_path = NULL;
968
glusterd_conf_t *priv = NULL;
970
struct stat stbuf = {
973
xlator_t *this = THIS;
976
GF_ASSERT(this->private);
977
GF_ASSERT(conf_path);
979
priv = this->private;
981
GF_VALIDATE_OR_GOTO("gsync", primary, out);
982
GF_VALIDATE_OR_GOTO("gsync", secondary, out);
984
len = snprintf(temp_conf_path, sizeof(temp_conf_path),
985
"%s/" GSYNC_CONF_TEMPLATE, priv->workdir);
986
if ((len < 0) || (len >= sizeof(temp_conf_path))) {
990
ret = sys_lstat(conf_path, &stbuf);
992
gf_msg_debug(this->name, 0, "Using passed config template(%s).",
994
working_conf_path = conf_path;
996
gf_msg(this->name, GF_LOG_WARNING, ENOENT, GD_MSG_FILE_OP_FAILED,
997
"Config file (%s) missing. Looking for template "
999
conf_path, temp_conf_path);
1000
ret = sys_lstat(temp_conf_path, &stbuf);
1002
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
1003
"Template config file (%s) missing.", temp_conf_path);
1006
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DEFAULT_TEMP_CONFIG,
1007
"Using default config template(%s).", temp_conf_path);
1008
working_conf_path = temp_conf_path;
1009
*is_template_in_use = _gf_true;
1014
ret = glusterd_gsync_get_param_file(pidfile, "pid", primary, secondary,
1016
if ((ret == -1) || strlen(pidfile) == 0) {
1017
if (*is_template_in_use == _gf_false) {
1018
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_PIDFILE_CREATE_FAILED,
1019
"failed to create the pidfile string. "
1020
"Trying default config template");
1021
working_conf_path = temp_conf_path;
1022
*is_template_in_use = _gf_true;
1026
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_PIDFILE_CREATE_FAILED,
1028
"create the pidfile string from template "
1034
gf_msg_debug(this->name, 0, "pidfile = %s", pidfile);
1036
ret = open(pidfile, O_RDWR);
1042
gsync_status_byfd(int fd)
1044
GF_ASSERT(fd >= -1);
1046
if (lockf(fd, F_TEST, 0) == -1 && (errno == EAGAIN || errno == EACCES))
1047
/* gsyncd keeps the pidfile locked */
1053
/* status: return 0 when gsync is running
1054
* return -1 when not running
1057
gsync_status(char *primary, char *secondary, char *conf_path, int *status,
1058
gf_boolean_t *is_template_in_use)
1060
char pidfile[PATH_MAX] = {
1065
fd = gsyncd_getpidfile(primary, secondary, pidfile, conf_path,
1066
is_template_in_use);
1070
*status = gsync_status_byfd(fd);
1078
glusterd_gsync_volinfo_dict_set(glusterd_volinfo_t *volinfo, char *key,
1082
char *gsync_status = NULL;
1083
xlator_t *this = THIS;
1085
gsync_status = gf_strdup(value);
1086
if (!gsync_status) {
1087
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
1088
"Unable to allocate memory");
1092
ret = dict_set_dynstr(volinfo->dict, key, gsync_status);
1094
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
1095
"Unable to set dict");
1105
glusterd_verify_gsyncd_spawn(char *primary, char *secondary)
1111
xlator_t *this = THIS;
1114
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "--verify", "spawning",
1116
runner_argprintf(&runner, ":%s", primary);
1117
runner_add_args(&runner, secondary, NULL);
1118
runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
1119
ret = runner_start(&runner);
1121
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SPAWNING_CHILD_FAILED,
1122
"spawning child failed");
1127
if (runner_end(&runner) != 0)
1131
gf_msg_debug(this->name, 0, "returning %d", ret);
1136
gsync_verify_config_options(dict_t *dict, char **op_errstr, char *volname)
1138
char **resopt = NULL;
1142
char *secondary = NULL;
1143
char *op_name = NULL;
1144
char *op_value = NULL;
1146
char errmsg[PATH_MAX] = "";
1147
gf_boolean_t banned = _gf_true;
1148
gf_boolean_t op_match = _gf_true;
1149
gf_boolean_t val_match = _gf_true;
1150
struct gsync_config_opt_vals_ *conf_vals = NULL;
1151
xlator_t *this = THIS;
1153
if (dict_get_str(dict, "subop", &subop) != 0) {
1154
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
1156
*op_errstr = gf_strdup("Invalid config request");
1160
if (dict_get_str(dict, "secondary", &secondary) != 0) {
1161
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
1162
GEOREP " CONFIG: no secondary given");
1163
*op_errstr = gf_strdup("Secondary required");
1167
if (strcmp(subop, "get-all") == 0)
1170
if (dict_get_str(dict, "op_name", &op_name) != 0) {
1171
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
1172
"option name missing");
1173
*op_errstr = gf_strdup("Option name missing");
1177
if (runcmd(GSYNCD_PREFIX "/gsyncd", "--config-check", op_name, NULL)) {
1178
ret = glusterd_verify_gsyncd_spawn(volname, secondary);
1180
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_SPAWN_FAILED,
1186
gf_msg(this->name, GF_LOG_WARNING, EINVAL, GD_MSG_INVALID_ENTRY,
1187
"Invalid option %s", op_name);
1188
*op_errstr = gf_strdup("Invalid option");
1193
if (strcmp(subop, "get") == 0)
1196
t = strtail(subop, "set");
1198
t = strtail(subop, "del");
1199
if (!t || (t[0] && strcmp(t, "-glob") != 0)) {
1200
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_SUBOP_NOT_FOUND,
1201
"unknown subop %s", subop);
1202
*op_errstr = gf_strdup("Invalid config request");
1206
if (strtail(subop, "set") &&
1207
dict_get_str(dict, "op_value", &op_value) != 0) {
1208
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
1209
"missing value for set");
1210
*op_errstr = gf_strdup("missing value");
1213
/* match option name against reserved options, modulo -/_
1216
for (resopt = gsync_reserved_opts; *resopt; resopt++) {
1218
for (i = 0; (*resopt)[i] && op_name[i]; i++) {
1219
if ((*resopt)[i] == op_name[i] ||
1220
((*resopt)[i] == '-' && op_name[i] == '_'))
1225
if (op_name[i] != '\0')
1229
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_RESERVED_OPTION,
1230
"Reserved option %s", op_name);
1231
*op_errstr = gf_strdup("Reserved option");
1238
/* Check options in gsync_confopt_vals for invalid values */
1239
for (conf_vals = gsync_confopt_vals; conf_vals->op_name; conf_vals++) {
1240
op_match = _gf_true;
1241
for (i = 0; conf_vals->op_name[i] && op_name[i]; i++) {
1242
if (conf_vals->op_name[i] == op_name[i] ||
1243
(conf_vals->op_name[i] == '_' && op_name[i] == '-'))
1245
op_match = _gf_false;
1251
val_match = _gf_false;
1252
for (i = 0; i < conf_vals->no_of_pos_vals; i++) {
1253
if (conf_vals->case_sensitive) {
1254
if (!strcmp(conf_vals->values[i], op_value))
1255
val_match = _gf_true;
1257
if (!strcasecmp(conf_vals->values[i], op_value))
1258
val_match = _gf_true;
1263
ret = snprintf(errmsg, sizeof(errmsg) - 1,
1264
"Invalid value(%s) for"
1269
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
1271
*op_errstr = gf_strdup(errmsg);
1281
glusterd_get_gsync_status_mst_slv(glusterd_volinfo_t *volinfo, char *secondary,
1282
char *conf_path, dict_t *rsp_dict,
1286
_get_status_mst_slv(dict_t *dict, char *key, data_t *value, void *data)
1288
glusterd_gsync_status_temp_t *param = NULL;
1289
char *secondary = NULL;
1290
char *secondary_buf = NULL;
1291
char *secondary_url = NULL;
1292
char *secondary_vol = NULL;
1293
char *secondary_host = NULL;
1294
char *errmsg = NULL;
1295
char conf_path[PATH_MAX] = "";
1297
glusterd_conf_t *priv = NULL;
1298
xlator_t *this = THIS;
1299
char sec_url[VOLINFO_SECONDARY_URL_MAX] = {0};
1301
param = (glusterd_gsync_status_temp_t *)data;
1303
GF_VALIDATE_OR_GOTO(this->name, param, out);
1304
GF_VALIDATE_OR_GOTO(this->name, param->volinfo, out);
1306
priv = this->private;
1307
GF_VALIDATE_OR_GOTO(this->name, priv, out);
1309
if (snprintf(sec_url, sizeof(sec_url), "%s", value->data) >=
1311
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
1312
"Error in copying secondary: %s!", value->data);
1316
ret = parse_secondary_url(sec_url, &secondary);
1318
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
1319
"Error in parsing secondary: %s!", value->data);
1323
ret = glusterd_get_secondary_info(secondary, &secondary_url,
1324
&secondary_host, &secondary_vol, &errmsg);
1327
gf_msg(this->name, GF_LOG_ERROR, 0,
1328
GD_MSG_SECONDARYINFO_FETCH_ERROR,
1329
"Unable to fetch secondary details. Error: %s", errmsg);
1331
gf_msg(this->name, GF_LOG_ERROR, 0,
1332
GD_MSG_SECONDARYINFO_FETCH_ERROR,
1333
"Unable to fetch secondary details.");
1338
ret = snprintf(conf_path, sizeof(conf_path) - 1,
1339
"%s/" GEOREP "/%s_%s_%s/gsyncd.conf", priv->workdir,
1340
param->volinfo->volname, secondary_host, secondary_vol);
1341
conf_path[ret] = '\0';
1343
ret = glusterd_get_gsync_status_mst_slv(
1344
param->volinfo, secondary, conf_path, param->rsp_dict, param->node);
1351
GF_FREE(secondary_buf);
1354
GF_FREE(secondary_vol);
1357
GF_FREE(secondary_url);
1360
GF_FREE(secondary_host);
1362
gf_msg_debug(this->name, 0, "Returning %d.", ret);
1367
_get_max_gsync_secondary_num(dict_t *dict, char *key, data_t *value, void *data)
1370
int *secnum = (int *)data;
1372
sscanf(key, "secondary%d", &tmp_secnum);
1373
if (tmp_secnum > *secnum)
1374
*secnum = tmp_secnum;
1380
_get_secondary_idx_secondary_voluuid(dict_t *dict, char *key, data_t *value,
1383
char *secondary_info = NULL;
1384
xlator_t *this = THIS;
1385
struct secondary_vol_config *sec_cfg = NULL;
1389
unsigned tmp_secnum = 0;
1394
secondary_info = value->data;
1396
if (!(secondary_info) || strlen(secondary_info) == 0) {
1397
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_SECONDARY,
1398
"Invalid secondary in dict");
1403
/* secondary format:
1404
* primary_node_uuid:ssh://secondary_host::secondary_vol:secondary_voluuid
1407
secondary_info = strchr(secondary_info, ':');
1411
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
1412
"secondary_info becomes NULL!");
1417
if (strcmp(secondary_info, sec_cfg->secondary_voluuid) == 0) {
1418
gf_msg_debug(this->name, 0,
1419
"Same secondary volume "
1420
"already present %s",
1421
sec_cfg->secondary_voluuid);
1424
sscanf(key, "secondary%d", &tmp_secnum);
1425
sec_cfg->old_slvidx = tmp_secnum;
1427
gf_msg_debug(this->name, 0,
1440
glusterd_remove_secondary_in_info(glusterd_volinfo_t *volinfo, char *secondary,
1443
int zero_secondary_entries = _gf_true;
1445
char *secondarykey = NULL;
1448
GF_ASSERT(secondary);
1451
ret = glusterd_get_secondary(volinfo, secondary, &secondarykey);
1452
if (ret < 0 && zero_secondary_entries) {
1456
zero_secondary_entries = _gf_false;
1457
dict_del(volinfo->gsync_secondaries, secondarykey);
1460
ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT);
1462
*op_errstr = gf_strdup(
1463
"Failed to store the Volume"
1468
gf_msg_debug(THIS->name, 0, "returning %d", ret);
1473
glusterd_gsync_get_uuid(char *secondary, glusterd_volinfo_t *vol, uuid_t uuid)
1476
char *secondarykey = NULL;
1477
char *secondaryentry = NULL;
1481
GF_ASSERT(secondary);
1483
ret = glusterd_get_secondary(vol, secondary, &secondarykey);
1485
/* XXX colliding cases of failure and non-extant
1486
* secondary... now just doing this as callers of this
1487
* function can make sense only of -1 and 0 as retvals;
1488
* getting at the proper semanticals will involve
1489
* fixing callers as well.
1495
ret = dict_get_str(vol->gsync_secondaries, secondarykey, &secondaryentry);
1496
GF_ASSERT(ret == 0);
1498
t = strchr(secondaryentry, ':');
1501
ret = gf_uuid_parse(secondaryentry, uuid);
1505
gf_msg_debug(THIS->name, 0, "Returning %d", ret);
1510
update_secondary_voluuid(dict_t *dict, char *key, data_t *value, void *data)
1512
char *secondary = NULL;
1513
char *secondary_url = NULL;
1514
char *secondary_vol = NULL;
1515
char *secondary_host = NULL;
1516
char *errmsg = NULL;
1517
xlator_t *this = THIS;
1519
char sec_url[VOLINFO_SECONDARY_URL_MAX] = {0};
1520
char secondary_voluuid[GF_UUID_BUF_SIZE] = {0};
1521
char *secondary_info = NULL;
1522
char *new_value = NULL;
1523
char *same_key = NULL;
1525
gf_boolean_t *voluuid_updated = NULL;
1527
voluuid_updated = data;
1528
secondary_info = value->data;
1529
gf_msg_debug(this->name, 0, "secondary_info: %s!", secondary_info);
1531
/* old secondary format:
1532
* primary_node_uuid:ssh://secondary_host::secondary_vol
1533
* New secondary format:
1534
* primary_node_uuid:ssh://secondary_host::secondary_vol:secondary_voluuid
1536
while (secondary_info) {
1537
secondary_info = strchr(secondary_info, ':');
1546
gf_msg_debug(this->name, 0, "cnt: %d", cnt);
1547
/* check whether old secondary format and update vol uuid if old format.
1548
* With volume uuid, number of ':' is 5 and is 4 without.
1551
if (snprintf(sec_url, sizeof(sec_url), "%s", value->data) >=
1553
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
1554
"Error in copying secondary: %s!", value->data);
1558
ret = parse_secondary_url(sec_url, &secondary);
1560
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
1561
"Error in parsing secondary: %s!", value->data);
1565
ret = glusterd_get_secondary_info(secondary, &secondary_url,
1566
&secondary_host, &secondary_vol,
1570
gf_msg(this->name, GF_LOG_ERROR, 0,
1571
GD_MSG_SECONDARYINFO_FETCH_ERROR,
1572
"Unable to fetch secondary details. Error: %s", errmsg);
1574
gf_msg(this->name, GF_LOG_ERROR, 0,
1575
GD_MSG_SECONDARYINFO_FETCH_ERROR,
1576
"Unable to fetch secondary details.");
1581
ret = glusterd_get_secondary_voluuid(secondary_host, secondary_vol,
1583
if ((ret) || (strlen(secondary_voluuid) == 0)) {
1584
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL,
1585
"Unable to get remote volume uuid"
1586
"secondaryhost:%s secondaryvol:%s",
1587
secondary_host, secondary_vol);
1588
/* Avoiding failure due to remote vol uuid fetch */
1592
ret = gf_asprintf(&new_value, "%s:%s", value->data, secondary_voluuid);
1593
ret = gf_asprintf(&same_key, "%s", key);
1595
/* delete old key and add new value */
1596
dict_del(dict, key);
1598
/* set new value for the same key*/
1599
ret = dict_set_dynstr(dict, same_key, new_value);
1601
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL,
1602
"Error in setting dict value"
1607
*voluuid_updated = _gf_true;
1616
GF_FREE(secondary_url);
1619
GF_FREE(secondary_vol);
1622
GF_FREE(secondary_host);
1626
gf_msg_debug(this->name, 0, "Returning %d.", ret);
1631
glusterd_update_secondary_voluuid_secondaryinfo(glusterd_volinfo_t *volinfo)
1634
xlator_t *this = THIS;
1635
gf_boolean_t voluuid_updated = _gf_false;
1637
GF_VALIDATE_OR_GOTO(this->name, volinfo, out);
1639
ret = dict_foreach(volinfo->gsync_secondaries, update_secondary_voluuid,
1642
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL,
1648
if (_gf_true == voluuid_updated) {
1649
ret = glusterd_store_volinfo(volinfo,
1650
GLUSTERD_VOLINFO_VER_AC_INCREMENT);
1652
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLINFO_STORE_FAIL,
1661
gf_msg_debug(this->name, 0, "Returning %d", ret);
1666
glusterd_check_gsync_running_local(char *primary, char *secondary,
1667
char *conf_path, gf_boolean_t *is_run)
1671
gf_boolean_t is_template_in_use = _gf_false;
1672
xlator_t *this = THIS;
1675
GF_ASSERT(secondary);
1678
*is_run = _gf_false;
1679
ret = gsync_status(primary, secondary, conf_path, &ret_status,
1680
&is_template_in_use);
1681
if (ret == 0 && ret_status == 0)
1683
else if (ret == -1) {
1684
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_VALIDATE_FAILED,
1685
GEOREP " validation failed");
1690
gf_msg_debug(this->name, 0, "Returning %d", ret);
1695
glusterd_store_secondary_in_info(glusterd_volinfo_t *volinfo, char *secondary,
1696
char *host_uuid, char *secondary_voluuid,
1697
char **op_errstr, gf_boolean_t is_force)
1701
char **linearr = NULL;
1703
char *secondarykey = NULL;
1704
char *secondaryentry = NULL;
1710
xlator_t *this = THIS;
1711
struct secondary_vol_config secondary1 = {
1716
GF_ASSERT(secondary);
1717
GF_ASSERT(host_uuid);
1718
GF_VALIDATE_OR_GOTO(this->name, secondary_voluuid, out);
1720
ret = glusterd_get_secondary(volinfo, secondary, &secondarykey);
1730
ret = dict_get_str(volinfo->gsync_secondaries, secondarykey,
1732
GF_ASSERT(ret == 0);
1734
/* same-name + same-uuid secondary entries should have been filtered
1735
* out in glusterd_op_verify_gsync_start_options(), so we can
1736
* assert an uuid mismatch
1738
t = strtail(secondaryentry, host_uuid);
1740
GF_ASSERT(!t || *t != ':');
1743
gf_msg_debug(this->name, 0,
1746
"been invoked for the %s (primary) and "
1747
"%s (secondary). Allowing without saving "
1748
"info again due to force command.",
1749
volinfo->volname, secondary);
1754
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVOKE_ERROR,
1756
" has already been invoked for "
1757
"the %s (primary) and %s (secondary) from a different "
1759
volinfo->volname, secondary);
1760
*op_errstr = gf_strdup(GEOREP
1761
" already running in "
1767
ret = glusterd_urltransform_single(secondary, "normalize", &linearr);
1771
ret = gf_asprintf(&value, "%s:%s:%s", host_uuid, linearr[0],
1774
glusterd_urltransform_free(linearr, 1);
1778
/* Given the secondary volume uuid, check and get any existing secondary */
1779
memcpy(secondary1.secondary_voluuid, secondary_voluuid,
1780
UUID_CANONICAL_FORM_LEN);
1781
ret = dict_foreach(volinfo->gsync_secondaries,
1782
_get_secondary_idx_secondary_voluuid, &secondary1);
1784
if (ret == 0) { /* New secondary */
1785
dict_foreach(volinfo->gsync_secondaries, _get_max_gsync_secondary_num,
1787
keylen = snprintf(key, sizeof(key), "secondary%d", maxslv + 1);
1789
ret = dict_set_dynstrn(volinfo->gsync_secondaries, key, keylen, value);
1794
} else if (ret == -1) { /* Existing secondary */
1795
keylen = snprintf(key, sizeof(key), "secondary%d",
1796
secondary1.old_slvidx);
1798
gf_msg_debug(this->name, 0,
1799
"Replacing key:%s with new value"
1803
/* Add new secondary's value, with the same secondary index */
1804
ret = dict_set_dynstrn(volinfo->gsync_secondaries, key, keylen, value);
1810
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL,
1811
"_get_secondary_idx_secondary_voluuid failed!");
1817
ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT);
1819
*op_errstr = gf_strdup(
1820
"Failed to store the Volume "
1830
glusterd_op_verify_gsync_start_options(glusterd_volinfo_t *volinfo,
1831
char *secondary, char *conf_path,
1832
char *statefile, char **op_errstr,
1833
gf_boolean_t is_force)
1837
gf_boolean_t is_template_in_use = _gf_false;
1838
char msg[2048] = {0};
1840
xlator_t *this = THIS;
1841
struct stat stbuf = {
1844
char statefiledir[PATH_MAX] = {
1847
char *statedir = NULL;
1850
GF_ASSERT(secondary);
1851
GF_ASSERT(op_errstr);
1852
GF_ASSERT(conf_path);
1853
GF_ASSERT(this->private);
1855
if (GLUSTERD_STATUS_STARTED != volinfo->status) {
1856
snprintf(msg, sizeof(msg),
1857
"Volume %s needs to be started "
1858
"before " GEOREP " start",
1863
/* check session directory as statefile may not present
1865
if (snprintf(statefiledir, sizeof(statefiledir), "%s", statefile) >=
1866
sizeof(statefiledir)) {
1867
snprintf(msg, sizeof(msg), "statefiledir truncated");
1868
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_FILE_OP_FAILED, "%s",
1870
*op_errstr = gf_strdup(msg);
1873
statedir = dirname(statefiledir);
1875
ret = sys_lstat(statedir, &stbuf);
1877
snprintf(msg, sizeof(msg),
1878
"Session between %s and %s has"
1879
" not been created. Please create session and retry.",
1880
volinfo->volname, secondary);
1881
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_FILE_OP_FAILED,
1882
"%s statefile: %s", msg, statefile);
1883
*op_errstr = gf_strdup(msg);
1887
/* Check if the gsync secondary info is stored. If not
1888
* session has not been created */
1889
ret = glusterd_gsync_get_uuid(secondary, volinfo, uuid);
1891
snprintf(msg, sizeof(msg),
1892
"Session between %s and %s has"
1893
" not been created. Please create session and retry.",
1894
volinfo->volname, secondary);
1895
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SESSION_CREATE_ERROR, "%s",
1900
/*Check if the gsync is already started in cmd. inited host
1901
* If so initiate add it into the glusterd's priv*/
1902
ret = gsync_status(volinfo->volname, secondary, conf_path, &ret_status,
1903
&is_template_in_use);
1905
if ((ret_status == 0) && !is_force) {
1906
snprintf(msg, sizeof(msg),
1909
" %s & %s already started",
1910
volinfo->volname, secondary);
1914
} else if (ret == -1) {
1915
snprintf(msg, sizeof(msg),
1918
"validation failed ");
1922
if (is_template_in_use == _gf_true) {
1923
snprintf(msg, sizeof(msg),
1926
"failed : pid-file entry missing "
1932
ret = glusterd_verify_gsyncd_spawn(volinfo->volname, secondary);
1933
if (ret && !is_force) {
1934
snprintf(msg, sizeof(msg), "Unable to spawn gsyncd");
1935
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_SPAWN_FAILED, "%s",
1939
if (ret && (msg[0] != '\0')) {
1940
*op_errstr = gf_strdup(msg);
1942
gf_msg_debug(this->name, 0, "Returning %d", ret);
1947
glusterd_check_geo_rep_configured(glusterd_volinfo_t *volinfo,
1953
if (volinfo->gsync_secondaries->count)
1962
* is_geo_rep_active:
1963
* This function reads the state_file and sets is_active to 1 if the
1964
* monitor status is neither "Stopped" or "Created"
1967
* 0: On successful read of state_file.
1972
is_geo_rep_active(glusterd_volinfo_t *volinfo, char *secondary, char *conf_path,
1975
dict_t *confd = NULL;
1976
char *statefile = NULL;
1977
char *primary = NULL;
1978
char monitor_status[PATH_MAX] = "";
1980
xlator_t *this = THIS;
1982
primary = volinfo->volname;
1986
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL,
1987
"Not able to create dict.");
1991
ret = glusterd_gsync_get_config(primary, secondary, conf_path, confd);
1993
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_CONFIG_INFO_FAILED,
1994
"Unable to get configuration data "
1995
"for %s(primary), %s(secondary)",
1996
primary, secondary);
2001
ret = dict_get_param(confd, "state_file", &statefile);
2003
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
2004
"Unable to get state_file's name "
2005
"for %s(primary), %s(secondary). Please check gsync "
2007
primary, secondary);
2012
ret = glusterd_gsync_read_frm_status(statefile, monitor_status,
2013
sizeof(monitor_status));
2015
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STAT_FILE_READ_FAILED,
2016
"Unable to read the status file for %s(primary), "
2018
primary, secondary);
2019
snprintf(monitor_status, sizeof(monitor_status), "defunct");
2022
if ((!strcmp(monitor_status, "Stopped")) ||
2023
(!strcmp(monitor_status, "Created"))) {
2036
* _get_secondary_status:
2037
* Called for each secondary in the volume from dict_foreach.
2038
* It calls is_geo_rep_active to get the monitor status.
2041
* 0: On successful read of state_file from is_geo_rep_active.
2042
* When it is found geo-rep is already active from previous calls.
2043
* When there is no secondary.
2048
_get_secondary_status(dict_t *dict, char *key, data_t *value, void *data)
2050
gsync_status_param_t *param = NULL;
2051
char *secondary = NULL;
2052
char *secondary_url = NULL;
2053
char *secondary_vol = NULL;
2054
char *secondary_host = NULL;
2055
char *errmsg = NULL;
2056
char conf_path[PATH_MAX] = "";
2058
glusterd_conf_t *priv = NULL;
2059
xlator_t *this = THIS;
2061
param = (gsync_status_param_t *)data;
2064
GF_ASSERT(param->volinfo);
2065
if (param->is_active) {
2070
priv = this->private;
2072
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
2073
"priv of glusterd not present");
2077
secondary = strchr(value->data, ':');
2084
ret = glusterd_get_secondary_info(secondary, &secondary_url,
2085
&secondary_host, &secondary_vol, &errmsg);
2088
gf_msg(this->name, GF_LOG_ERROR, 0,
2089
GD_MSG_SECONDARYINFO_FETCH_ERROR,
2091
" secondary details. Error: %s",
2094
gf_msg(this->name, GF_LOG_ERROR, 0,
2095
GD_MSG_SECONDARYINFO_FETCH_ERROR,
2096
"Unable to fetch secondary details.");
2101
ret = snprintf(conf_path, sizeof(conf_path) - 1,
2102
"%s/" GEOREP "/%s_%s_%s/gsyncd.conf", priv->workdir,
2103
param->volinfo->volname, secondary_host, secondary_vol);
2105
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CONF_PATH_ASSIGN_FAILED,
2106
"Unable to assign conf_path.");
2110
conf_path[ret] = '\0';
2112
ret = is_geo_rep_active(param->volinfo, secondary, conf_path,
2119
GF_FREE(secondary_vol);
2122
GF_FREE(secondary_url);
2124
GF_FREE(secondary_host);
2129
/* glusterd_check_geo_rep_running:
2130
* Checks if any geo-rep session is running for the volume.
2133
* Sets param.active to true if any geo-rep session is active.
2134
* This function sets op_errstr during some error and when any geo-rep
2135
* session is active. It is caller's responsibility to free op_errstr
2140
glusterd_check_geo_rep_running(gsync_status_param_t *param, char **op_errstr)
2145
gf_boolean_t enabled = _gf_false;
2149
GF_ASSERT(param->volinfo);
2150
GF_ASSERT(op_errstr);
2152
glusterd_check_geo_rep_configured(param->volinfo, &enabled);
2155
ret = dict_foreach(param->volinfo->gsync_secondaries,
2156
_get_secondary_status, param);
2158
gf_msg(THIS->name, GF_LOG_ERROR, 0,
2159
GD_MSG_SECONDARYINFO_FETCH_ERROR,
2160
"_get_secondary_satus failed");
2161
snprintf(msg, sizeof(msg),
2164
" get the status of active " GEOREP
2166
" session for the volume '%s'.\n"
2167
" Please check the log file for"
2169
param->volinfo->volname);
2170
*op_errstr = gf_strdup(msg);
2175
if (param->is_active) {
2176
snprintf(msg, sizeof(msg),
2179
" are active for the volume %s.\nStop"
2181
" sessions involved in this"
2182
" volume. Use 'volume " GEOREP
2183
" status' command for more info.",
2184
param->volinfo->volname);
2185
*op_errstr = gf_strdup(msg);
2194
glusterd_op_verify_gsync_running(glusterd_volinfo_t *volinfo, char *secondary,
2195
char *conf_path, char **op_errstr)
2199
char msg[2048] = {0};
2200
char pidfile[PATH_MAX] = {
2203
gf_boolean_t is_template_in_use = _gf_false;
2204
xlator_t *this = THIS;
2207
GF_ASSERT(secondary);
2208
GF_ASSERT(conf_path);
2209
GF_ASSERT(op_errstr);
2211
if (GLUSTERD_STATUS_STARTED != volinfo->status) {
2212
snprintf(msg, sizeof(msg),
2213
"Volume %s needs to be started "
2214
"before " GEOREP " start",
2216
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_GEO_REP_START_FAILED,
2217
"Volume is not in a started state, Volname=%s",
2218
volinfo->volname, NULL);
2223
pfd = gsyncd_getpidfile(volinfo->volname, secondary, pidfile, conf_path,
2224
&is_template_in_use);
2226
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VALIDATE_FAILED,
2227
GEOREP " stop validation failed for %s & %s", volinfo->volname,
2232
if (gsync_status_byfd(pfd) == -1) {
2233
snprintf(msg, sizeof(msg),
2235
" session b/w %s & %s is "
2236
"not running on this node.",
2237
volinfo->volname, secondary);
2238
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SESSION_INACTIVE, "%s", msg);
2240
/* monitor gsyncd already dead */
2244
if (is_template_in_use) {
2245
snprintf(msg, sizeof(msg),
2246
"pid-file entry missing in "
2247
"the config file(%s).",
2249
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PIDFILE_NOT_FOUND, "%s",
2260
if (ret && (msg[0] != '\0')) {
2261
*op_errstr = gf_strdup(msg);
2263
gf_msg_debug(this->name, 0, "Returning %d", ret);
2268
glusterd_verify_gsync_status_opts(dict_t *dict, char **op_errstr)
2270
char *secondary = NULL;
2271
char *volname = NULL;
2272
char errmsg[PATH_MAX] = {
2275
glusterd_volinfo_t *volinfo = NULL;
2277
char *conf_path = NULL;
2278
char *secondary_url = NULL;
2279
char *secondary_host = NULL;
2280
char *secondary_vol = NULL;
2281
glusterd_conf_t *priv = NULL;
2282
xlator_t *this = THIS;
2284
priv = this->private;
2286
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
2287
"priv of glusterd not present");
2288
*op_errstr = gf_strdup("glusterd defunct");
2292
ret = dict_get_str(dict, "primary", &volname);
2298
ret = glusterd_volinfo_find(volname, &volinfo);
2300
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_VOL_NOT_FOUND,
2301
"volume name does not exist");
2302
snprintf(errmsg, sizeof(errmsg),
2303
"Volume name %s does not"
2306
*op_errstr = gf_strdup(errmsg);
2310
ret = dict_get_str(dict, "secondary", &secondary);
2316
ret = glusterd_get_secondary_details_confpath(
2317
volinfo, dict, &secondary_url, &secondary_host, &secondary_vol,
2318
&conf_path, op_errstr);
2320
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARYINFO_FETCH_ERROR,
2321
"Unable to fetch secondary or confpath details.");
2327
gf_msg_debug(this->name, 0, "Returning %d", ret);
2332
glusterd_op_gsync_args_get(dict_t *dict, char **op_errstr, char **primary,
2333
char **secondary, char **host_uuid)
2336
xlator_t *this = THIS;
2339
GF_ASSERT(op_errstr);
2342
ret = dict_get_str(dict, "primary", primary);
2344
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
2345
"primary not found");
2346
*op_errstr = gf_strdup("primary not found");
2352
ret = dict_get_str(dict, "secondary", secondary);
2354
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
2355
"secondary not found");
2356
*op_errstr = gf_strdup("secondary not found");
2362
ret = dict_get_str(dict, "host-uuid", host_uuid);
2364
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
2365
"host_uuid not found");
2366
*op_errstr = gf_strdup("host_uuid not found");
2373
gf_msg_debug(this->name, 0, "Returning %d", ret);
2378
glusterd_op_stage_sys_exec(dict_t *dict, char **op_errstr)
2380
char errmsg[PATH_MAX] = "";
2381
char *command = NULL;
2382
char command_path[PATH_MAX] = "";
2387
glusterd_conf_t *conf = NULL;
2388
xlator_t *this = THIS;
2390
conf = this->private;
2393
if (conf->op_version < 2) {
2394
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNSUPPORTED_VERSION,
2395
"Op Version not supported.");
2396
snprintf(errmsg, sizeof(errmsg),
2397
"One or more nodes do not"
2398
" support the required op version.");
2399
*op_errstr = gf_strdup(errmsg);
2404
ret = dict_get_str(dict, "command", &command);
2406
strcpy(errmsg, "internal error");
2407
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
2408
"Unable to get command from dict");
2412
/* enforce local occurrence of the command */
2413
if (strchr(command, '/')) {
2414
strcpy(errmsg, "invalid command name");
2419
sprintf(command_path, GSYNCD_PREFIX "/peer_%s", command);
2420
/* check if it's executable */
2421
ret = sys_access(command_path, X_OK);
2423
/* check if it's a regular file */
2424
ret = sys_stat(command_path, &st);
2425
if (!ret && !S_ISREG(st.st_mode))
2430
if (errmsg[0] == '\0') {
2432
snprintf(errmsg, sizeof(errmsg),
2433
"gsync peer_%s command not found.", command);
2435
snprintf(errmsg, sizeof(errmsg), "%s",
2436
"gsync peer command was not "
2439
*op_errstr = gf_strdup(errmsg);
2440
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PEER_CMD_ERROR, "%s",
2444
gf_msg_debug(this->name, 0, "Returning %d", ret);
2449
glusterd_op_stage_copy_file(dict_t *dict, char **op_errstr)
2451
char abs_filename[PATH_MAX] = "";
2452
char errmsg[PATH_MAX] = "";
2453
char *filename = NULL;
2454
char *host_uuid = NULL;
2455
char uuid_str[64] = {0};
2457
glusterd_conf_t *priv = NULL;
2458
struct stat stbuf = {
2461
xlator_t *this = THIS;
2462
char workdir[PATH_MAX] = {
2465
char realpath_filename[PATH_MAX] = {
2468
char realpath_workdir[PATH_MAX] = {
2473
priv = this->private;
2475
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
2476
"priv of glusterd not present");
2477
*op_errstr = gf_strdup("glusterd defunct");
2481
if (priv->op_version < 2) {
2482
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNSUPPORTED_VERSION,
2483
"Op Version not supported.");
2484
snprintf(errmsg, sizeof(errmsg),
2485
"One or more nodes do not"
2486
" support the required op version.");
2487
*op_errstr = gf_strdup(errmsg);
2492
ret = dict_get_str(dict, "host-uuid", &host_uuid);
2494
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
2495
"Unable to fetch host-uuid from dict.");
2499
uuid_utoa_r(MY_UUID, uuid_str);
2500
if (!strcmp(uuid_str, host_uuid)) {
2501
ret = dict_get_str(dict, "source", &filename);
2503
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
2504
"Unable to fetch filename from dict.");
2505
*op_errstr = gf_strdup("command unsuccessful");
2508
len = snprintf(abs_filename, sizeof(abs_filename), "%s/%s",
2509
priv->workdir, filename);
2510
if ((len < 0) || (len >= sizeof(abs_filename))) {
2511
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_COPY_FAIL, NULL);
2516
if (!realpath(priv->workdir, realpath_workdir)) {
2517
len = snprintf(errmsg, sizeof(errmsg),
2519
"get realpath of %s: %s",
2520
priv->workdir, strerror(errno));
2522
strcpy(errmsg, "<error>");
2524
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_REALPATH_GET_FAIL,
2525
"Realpath=%s, Reason=%s", priv->workdir, strerror(errno),
2527
*op_errstr = gf_strdup(errmsg);
2532
if (!realpath(abs_filename, realpath_filename)) {
2533
snprintf(errmsg, sizeof(errmsg),
2535
"realpath of %s: %s",
2536
filename, strerror(errno));
2537
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_REALPATH_GET_FAIL,
2538
"Filename=%s, Reason=%s", filename, strerror(errno), NULL);
2539
*op_errstr = gf_strdup(errmsg);
2544
/* Add Trailing slash to workdir, without slash strncmp
2545
will succeed for /var/lib/glusterd_bad */
2546
len = snprintf(workdir, sizeof(workdir), "%s/", realpath_workdir);
2547
if ((len < 0) || (len >= sizeof(workdir))) {
2548
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_COPY_FAIL, NULL);
2553
/* Protect against file copy outside $workdir */
2554
if (strncmp(workdir, realpath_filename, strlen(workdir))) {
2555
len = snprintf(errmsg, sizeof(errmsg),
2557
" is outside of %s directory",
2560
strcpy(errmsg, "<error>");
2562
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_SRC_FILE_ERROR, errmsg,
2564
*op_errstr = gf_strdup(errmsg);
2569
ret = sys_lstat(abs_filename, &stbuf);
2571
len = snprintf(errmsg, sizeof(errmsg),
2573
" does not exist in %s",
2576
strcpy(errmsg, "<error>");
2578
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_SRC_FILE_ERROR, errmsg,
2580
*op_errstr = gf_strdup(errmsg);
2584
if (!S_ISREG(stbuf.st_mode)) {
2585
snprintf(errmsg, sizeof(errmsg),
2587
" is not a regular file.");
2588
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_SRC_FILE_ERROR, errmsg,
2590
*op_errstr = gf_strdup(errmsg);
2598
gf_msg_debug(this->name, 0, "Returning %d", ret);
2603
glusterd_get_statefile_name(glusterd_volinfo_t *volinfo, char *secondary,
2604
char *conf_path, char **statefile,
2605
gf_boolean_t *is_template_in_use)
2607
char *primary = NULL;
2609
char *working_conf_path = NULL;
2610
char temp_conf_path[PATH_MAX] = "";
2611
dict_t *confd = NULL;
2612
glusterd_conf_t *priv = NULL;
2614
struct stat stbuf = {
2617
xlator_t *this = THIS;
2620
GF_ASSERT(this->private);
2622
GF_ASSERT(conf_path);
2623
GF_ASSERT(is_template_in_use);
2625
primary = volinfo->volname;
2629
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL,
2630
"Unable to create new dict");
2634
priv = THIS->private;
2636
len = snprintf(temp_conf_path, sizeof(temp_conf_path),
2637
"%s/" GSYNC_CONF_TEMPLATE, priv->workdir);
2638
if ((len < 0) || (len >= sizeof(temp_conf_path))) {
2642
ret = sys_lstat(conf_path, &stbuf);
2644
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_CONFIG_INFO,
2645
"Using passed config template(%s).", conf_path);
2646
working_conf_path = conf_path;
2648
gf_msg(this->name, GF_LOG_WARNING, ENOENT, GD_MSG_FILE_OP_FAILED,
2649
"Config file (%s) missing. Looking for template config"
2651
conf_path, temp_conf_path);
2652
ret = sys_lstat(temp_conf_path, &stbuf);
2654
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
2656
"config file (%s) missing.",
2660
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DEFAULT_TEMP_CONFIG,
2661
"Using default config template(%s).", temp_conf_path);
2662
working_conf_path = temp_conf_path;
2663
*is_template_in_use = _gf_true;
2667
ret = glusterd_gsync_get_config(primary, secondary, working_conf_path,
2670
if (*is_template_in_use == _gf_false) {
2671
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_CONFIG_INFO_FAILED,
2672
"Unable to get configuration data "
2673
"for %s(primary), %s(secondary). "
2674
"Trying template config.",
2675
primary, secondary);
2676
working_conf_path = temp_conf_path;
2677
*is_template_in_use = _gf_true;
2680
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_CONFIG_INFO_FAILED,
2681
"Unable to get configuration data "
2682
"for %s(primary), %s(secondary) from "
2684
primary, secondary);
2689
ret = dict_get_param(confd, "state_file", &buf);
2691
if (*is_template_in_use == _gf_false) {
2692
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
2693
"Unable to get state_file's name. "
2694
"Trying template config.");
2695
working_conf_path = temp_conf_path;
2696
*is_template_in_use = _gf_true;
2699
gf_msg(this->name, GF_LOG_ERROR, 0,
2700
GD_MSG_GET_STATEFILE_NAME_FAILED,
2701
"Unable to get state_file's "
2702
"name from template.");
2710
*statefile = gf_strdup(buf);
2718
gf_msg_debug(this->name, 0, "Returning %d ", ret);
2723
glusterd_create_status_file(char *primary, char *secondary,
2724
char *secondary_host, char *secondary_vol,
2731
glusterd_conf_t *priv = NULL;
2732
xlator_t *this = THIS;
2734
priv = this->private;
2736
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
2737
"priv of glusterd not present");
2742
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STATUS_NULL, "Status Empty");
2745
gf_msg_debug(this->name, 0, "secondary = %s", secondary);
2748
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "--create", status, "-c",
2750
runner_argprintf(&runner, "%s/" GEOREP "/%s_%s_%s/gsyncd.conf",
2751
priv->workdir, primary, secondary_host, secondary_vol);
2752
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
2753
runner_argprintf(&runner, ":%s", primary);
2754
runner_add_args(&runner, secondary, NULL);
2755
synclock_unlock(&priv->big_lock);
2756
ret = runner_run(&runner);
2757
synclock_lock(&priv->big_lock);
2759
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STATUSFILE_CREATE_FAILED,
2760
"Creating status file failed.");
2767
gf_msg_debug(this->name, 0, "returning %d", ret);
2772
glusterd_verify_secondary(char *volname, char *secondary_url,
2773
char *secondary_vol, int ssh_port, char **op_errstr,
2774
gf_boolean_t *is_force_blocker)
2780
char log_file_path[PATH_MAX] = "";
2781
char buf[PATH_MAX] = "";
2783
char *secondary_url_buf = NULL;
2784
char *save_ptr = NULL;
2785
char *secondary_user = NULL;
2786
char *secondary_ip = NULL;
2787
glusterd_conf_t *priv = NULL;
2788
xlator_t *this = THIS;
2791
priv = this->private;
2794
GF_ASSERT(secondary_url);
2795
GF_ASSERT(secondary_vol);
2797
/* Fetch the secondary_user and secondary_ip from the secondary_url.
2798
* If the secondary_user is not present. Use "root"
2800
if (strstr(secondary_url, "@")) {
2801
secondary_url_buf = gf_strdup(secondary_url);
2802
if (!secondary_url_buf) {
2803
gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_STRDUP_FAILED,
2804
"Secondary_url=%s", secondary_url, NULL);
2808
secondary_user = strtok_r(secondary_url_buf, "@", &save_ptr);
2809
secondary_ip = strtok_r(NULL, "@", &save_ptr);
2811
secondary_user = "root";
2812
secondary_ip = secondary_url;
2815
if (!secondary_user || !secondary_ip) {
2816
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_URL_INVALID,
2817
"Invalid secondary url.");
2821
snprintf(log_file_path, sizeof(log_file_path), "%s/create_verify_log",
2825
runner_add_args(&runner, GSYNCD_PREFIX "/gverify.sh", NULL);
2826
runner_argprintf(&runner, "%s", volname);
2827
runner_argprintf(&runner, "%s", secondary_user);
2828
runner_argprintf(&runner, "%s", secondary_ip);
2829
runner_argprintf(&runner, "%s", secondary_vol);
2830
runner_argprintf(&runner, "%d", ssh_port);
2831
runner_argprintf(&runner, "%s", log_file_path);
2832
ret = dict_get_str(this->options, "transport.address-family", &af);
2836
runner_argprintf(&runner, "%s", af);
2838
gf_msg_debug(this->name, 0, "gverify Args = %s %s %s %s %s %s %s %s",
2839
runner.argv[0], runner.argv[1], runner.argv[2], runner.argv[3],
2840
runner.argv[4], runner.argv[5], runner.argv[6],
2842
runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
2843
synclock_unlock(&priv->big_lock);
2844
ret = runner_run(&runner);
2845
synclock_lock(&priv->big_lock);
2847
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_SECONDARY,
2848
"Not a valid secondary");
2849
ret = glusterd_gsync_read_frm_status(log_file_path, buf, sizeof(buf));
2851
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_READ_ERROR,
2852
"Unable to read from %s", log_file_path);
2856
/* Tokenize the error message from gverify.sh to figure out
2857
* if the error is a force blocker or not. */
2858
tmp = strtok_r(buf, "|", &save_ptr);
2863
if (!strcmp(tmp, "FORCE_BLOCKER"))
2864
*is_force_blocker = 1;
2866
/* No FORCE_BLOCKER flag present so all that is
2867
* present is the error message. */
2868
*is_force_blocker = 0;
2869
*op_errstr = gf_strdup(tmp);
2874
/* Copy rest of the error message to op_errstr */
2875
tmp = strtok_r(NULL, "|", &save_ptr);
2877
*op_errstr = gf_strdup(tmp);
2883
GF_FREE(secondary_url_buf);
2884
sys_unlink(log_file_path);
2885
gf_msg_debug(this->name, 0, "Returning %d", ret);
2889
/** @secondary_ip remains unmodified */
2891
glusterd_geo_rep_parse_secondary(char *secondary_url, char **hostname,
2896
char *save_ptr = NULL;
2898
char errmsg[PATH_MAX] = "";
2899
char *saved_url = NULL;
2900
xlator_t *this = THIS;
2902
GF_ASSERT(secondary_url);
2903
GF_ASSERT(*secondary_url);
2905
saved_url = gf_strdup(secondary_url);
2909
/* Checking if hostname has user specified */
2910
host = strstr(saved_url, "@");
2911
if (!host) { /* no user specified */
2913
*hostname = gf_strdup(saved_url);
2921
/* Moving the host past the '@' and checking if the
2922
* actual hostname also has '@' */
2924
if (strstr(host, "@")) {
2925
gf_msg_debug(this->name, 0, "host = %s", host);
2926
ret = snprintf(errmsg, sizeof(errmsg) - 1, "Invalid Hostname (%s).",
2929
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY, "%s",
2933
*op_errstr = gf_strdup(errmsg);
2940
* preliminary check for valid secondary format.
2942
tmp = strtok_r(saved_url, "@", &save_ptr);
2943
tmp = strtok_r(NULL, "@", &save_ptr);
2947
*hostname = gf_strdup(tmp);
2959
gf_msg_debug(this->name, 0, "Returning %d", ret);
2963
/* Return -1 only if there is a match in volume uuid */
2965
get_secondaryhost_from_voluuid(dict_t *dict, char *key, data_t *value,
2968
char *secondary_info = NULL;
2970
char *secondary_host = NULL;
2971
xlator_t *this = THIS;
2972
struct secondary_vol_config *secondary_vol = NULL;
2976
secondary_vol = data;
2977
secondary_info = value->data;
2979
gf_msg_debug(this->name, 0, "secondary_info:%s !", secondary_info);
2981
if (!(secondary_info) || strlen(secondary_info) == 0) {
2982
/* no secondaries present, peace */
2987
/* secondary format:
2988
* primary_node_uuid:ssh://secondary_host::secondary_vol:secondary_voluuid
2991
secondary_info = strchr(secondary_info, ':');
2998
if (!(secondary_info) || strlen(secondary_info) == 0) {
2999
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_VOL_PARSE_FAIL,
3000
"secondary_info format is wrong!");
3004
if (strcmp(secondary_info, secondary_vol->secondary_voluuid) == 0) {
3007
/* get corresponding secondary host for reference*/
3008
secondary_host = value->data;
3009
secondary_host = strstr(secondary_host, "://");
3010
if (secondary_host) {
3011
secondary_host += 3;
3013
gf_msg(this->name, GF_LOG_ERROR, 0,
3014
GD_MSG_SECONDARY_VOL_PARSE_FAIL,
3015
"Invalid secondary_host format!");
3019
/* To go past username in non-root geo-rep session */
3020
tmp = strchr(secondary_host, '@');
3022
if ((tmp - secondary_host) >= LOGIN_NAME_MAX) {
3023
gf_msg(this->name, GF_LOG_ERROR, 0,
3024
GD_MSG_SECONDARY_VOL_PARSE_FAIL,
3025
"Invalid secondary user length in %s",
3030
strncpy(secondary_vol->old_secuser, secondary_host,
3031
(tmp - secondary_host));
3032
secondary_vol->old_secuser[(tmp - secondary_host) + 1] = '\0';
3033
secondary_host = tmp + 1;
3035
strcpy(secondary_vol->old_secuser, "root");
3037
tmp = strchr(secondary_host, ':');
3039
gf_msg(this->name, GF_LOG_ERROR, 0,
3040
GD_MSG_SECONDARY_VOL_PARSE_FAIL,
3041
"Invalid secondary_host!");
3046
strncpy(secondary_vol->old_sechost, secondary_host,
3047
(tmp - secondary_host));
3048
secondary_vol->old_sechost[(tmp - secondary_host) + 1] = '\0';
3059
/* Given secondary host and secondary volume, check whether secondary volume
3060
* uuid already present. If secondary volume uuid is present, get corresponding
3061
* secondary host for reference */
3063
glusterd_get_secondaryhost_from_voluuid(glusterd_volinfo_t *volinfo,
3064
char *secondary_host,
3065
char *secondary_vol,
3066
struct secondary_vol_config *secondary1)
3070
GF_VALIDATE_OR_GOTO(THIS->name, volinfo, out);
3072
ret = dict_foreach(volinfo->gsync_secondaries,
3073
get_secondaryhost_from_voluuid, secondary1);
3079
glusterd_op_stage_gsync_create(dict_t *dict, char **op_errstr)
3081
char *down_peerstr = NULL;
3082
char *secondary = NULL;
3083
char *volname = NULL;
3084
char *host_uuid = NULL;
3085
char *statefile = NULL;
3086
char *secondary_url = NULL;
3087
char *secondary_host = NULL;
3088
char *secondary_vol = NULL;
3089
char *conf_path = NULL;
3090
char errmsg[PATH_MAX] = "";
3091
char common_pem_file[PATH_MAX] = "";
3092
char hook_script[PATH_MAX] = "";
3093
char uuid_str[64] = "";
3095
int is_pem_push = -1;
3097
gf_boolean_t is_force = -1;
3098
gf_boolean_t is_no_verify = -1;
3099
gf_boolean_t is_force_blocker = -1;
3100
gf_boolean_t is_template_in_use = _gf_false;
3101
glusterd_conf_t *conf = NULL;
3102
glusterd_volinfo_t *volinfo = NULL;
3103
struct stat stbuf = {
3106
xlator_t *this = THIS;
3107
struct secondary_vol_config secondary1 = {
3110
char old_secondary_url[SECONDARY_URL_INFO_MAX] = {0};
3111
char old_confpath[PATH_MAX] = {0};
3112
gf_boolean_t is_running = _gf_false;
3113
char *statedir = NULL;
3114
char statefiledir[PATH_MAX] = {
3117
gf_boolean_t is_different_secondaryhost = _gf_false;
3118
gf_boolean_t is_different_username = _gf_false;
3119
char *secondary_user = NULL;
3120
char *save_ptr = NULL;
3121
char *secondary_url_buf = NULL;
3124
conf = this->private;
3127
ret = glusterd_op_gsync_args_get(dict, op_errstr, &volname, &secondary,
3130
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_ARG_FETCH_ERROR,
3131
"Unable to fetch arguments");
3132
gf_msg_debug(this->name, 0, "Returning %d", ret);
3136
if (conf->op_version < 2) {
3137
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNSUPPORTED_VERSION,
3138
"Op Version not supported.");
3139
snprintf(errmsg, sizeof(errmsg),
3140
"One or more nodes do not"
3141
" support the required op version.");
3142
*op_errstr = gf_strdup(errmsg);
3147
ret = glusterd_volinfo_find(volname, &volinfo);
3149
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_VOL_NOT_FOUND,
3150
"volume name does not exist");
3151
snprintf(errmsg, sizeof(errmsg),
3152
"Volume name %s does not"
3158
ret = glusterd_get_secondary_details_confpath(
3159
volinfo, dict, &secondary_url, &secondary_host, &secondary_vol,
3160
&conf_path, op_errstr);
3162
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARYINFO_FETCH_ERROR,
3163
"Unable to fetch secondary or confpath details.");
3168
is_force = dict_get_str_boolean(dict, "force", _gf_false);
3170
uuid_utoa_r(MY_UUID, uuid_str);
3171
if (!strcmp(uuid_str, host_uuid)) {
3172
ret = glusterd_are_vol_all_peers_up(volinfo, &conf->peers,
3174
if ((ret == _gf_false) && !is_force) {
3175
snprintf(errmsg, sizeof(errmsg),
3177
" which is a part of %s volume, is"
3178
" down. Please bring up the peer and"
3180
down_peerstr, volinfo->volname);
3181
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PEER_DISCONNECTED, "%s",
3183
*op_errstr = gf_strdup(errmsg);
3184
GF_FREE(down_peerstr);
3185
down_peerstr = NULL;
3186
gf_msg_debug(this->name, 0, "Returning %d", ret);
3188
} else if (ret == _gf_false) {
3189
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_PEER_DISCONNECTED,
3190
"Peer %s, which is a part of %s volume, is"
3191
" down. Force creating geo-rep session."
3192
" On bringing up the peer, re-run"
3193
" \"gluster system:: execute"
3194
" gsec_create\" and \"gluster volume"
3195
" geo-replication %s %s create push-pem"
3197
down_peerstr, volinfo->volname, volinfo->volname, secondary);
3198
GF_FREE(down_peerstr);
3199
down_peerstr = NULL;
3202
ret = dict_get_int32(dict, "ssh_port", &ssh_port);
3203
if (ret < 0 && ret != -ENOENT) {
3204
snprintf(errmsg, sizeof(errmsg),
3205
"Fetching ssh_port failed while "
3206
"handling " GEOREP " options");
3207
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
3212
is_no_verify = dict_get_str_boolean(dict, "no_verify", _gf_false);
3214
if (!is_no_verify) {
3215
/* Checking if secondary host is pingable, has proper passwordless
3216
* ssh login setup, secondary volume is created, secondary vol is
3217
* empty, and if it has enough memory and bypass in case of force if
3218
* the error is not a force blocker */
3219
ret = glusterd_verify_secondary(volname, secondary_url,
3220
secondary_vol, ssh_port, op_errstr,
3223
if (is_force && !is_force_blocker) {
3224
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_INVALID_SECONDARY,
3225
"%s is not a valid secondary "
3226
"volume. Error: %s. Force "
3229
secondary, *op_errstr);
3231
gf_msg(this->name, GF_LOG_ERROR, 0,
3232
GD_MSG_INVALID_SECONDARY,
3233
"%s is not a valid secondary "
3234
"volume. Error: %s",
3235
secondary, *op_errstr);
3243
ret = dict_get_int32(dict, "push_pem", &is_pem_push);
3244
if (!ret && is_pem_push) {
3245
ret = snprintf(common_pem_file, sizeof(common_pem_file),
3246
"%s" GLUSTERD_COMMON_PEM_PUB_FILE, conf->workdir);
3247
if ((ret < 0) || (ret >= sizeof(common_pem_file))) {
3252
ret = snprintf(hook_script, sizeof(hook_script),
3253
"%s" GLUSTERD_CREATE_HOOK_SCRIPT, conf->workdir);
3254
if ((ret < 0) || (ret >= sizeof(hook_script))) {
3259
ret = sys_lstat(common_pem_file, &stbuf);
3261
len = snprintf(errmsg, sizeof(errmsg),
3263
" required for push-pem is"
3264
" not present. Please run"
3265
" \"gluster system:: execute"
3269
strcpy(errmsg, "<error>");
3271
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
3273
*op_errstr = gf_strdup(errmsg);
3278
ret = sys_lstat(hook_script, &stbuf);
3280
len = snprintf(errmsg, sizeof(errmsg),
3281
"The hook-script (%s) "
3282
"required for push-pem is not "
3283
"present. Please install the "
3284
"hook-script and retry",
3287
strcpy(errmsg, "<error>");
3289
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
3291
*op_errstr = gf_strdup(errmsg);
3296
if (!S_ISREG(stbuf.st_mode)) {
3297
len = snprintf(errmsg, sizeof(errmsg),
3299
" required for push-pem is"
3300
" not a regular file. Please"
3301
" run \"gluster system:: "
3302
"execute gsec_create\"",
3305
strcpy(errmsg, "<error>");
3307
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REG_FILE_MISSING,
3315
ret = glusterd_get_statefile_name(volinfo, secondary, conf_path, &statefile,
3316
&is_template_in_use);
3318
if (!strstr(secondary, "::"))
3319
snprintf(errmsg, sizeof(errmsg), "%s is not a valid secondary url.",
3322
snprintf(errmsg, sizeof(errmsg),
3323
"Please check gsync "
3324
"config file. Unable to get statefile's name");
3325
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STATEFILE_NAME_NOT_FOUND,
3331
ret = dict_set_str(dict, "statefile", statefile);
3333
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
3334
"Unable to store statefile path");
3338
if (snprintf(statefiledir, sizeof(statefiledir), "%s", statefile) >=
3339
sizeof(statefiledir)) {
3340
snprintf(errmsg, sizeof(errmsg), "Failed copying statefiledir");
3343
statedir = dirname(statefiledir);
3345
ret = sys_lstat(statedir, &stbuf);
3346
if (!ret && !is_force) {
3347
snprintf(errmsg, sizeof(errmsg),
3348
"Session between %s"
3349
" and %s is already created.",
3350
volinfo->volname, secondary);
3351
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SESSION_ALREADY_EXIST, "%s",
3356
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_FORCE_CREATE_SESSION,
3357
"Session between %s and %s is already created. Force"
3359
volinfo->volname, secondary);
3361
ret = glusterd_get_secondary_voluuid(secondary_host, secondary_vol,
3362
secondary1.secondary_voluuid);
3363
if ((ret) || (strlen(secondary1.secondary_voluuid) == 0)) {
3364
snprintf(errmsg, sizeof(errmsg), "Unable to get remote volume uuid.");
3365
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL, "%s",
3371
ret = dict_set_dynstr_with_alloc(dict, "secondary_voluuid",
3372
secondary1.secondary_voluuid);
3374
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
3375
"Unable to set secondary volume uuid in the dict");
3379
/* Check whether session is already created using secondary volume uuid */
3380
ret = glusterd_get_secondaryhost_from_voluuid(volinfo, secondary_host,
3381
secondary_vol, &secondary1);
3384
snprintf(errmsg, sizeof(errmsg),
3385
"Session between %s"
3386
" and %s:%s is already created! Cannot create "
3387
"with new secondary:%s again!",
3388
volinfo->volname, secondary1.old_sechost, secondary_vol,
3390
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FORCE_CREATE_SESSION,
3392
" %s and %s:%s is already created! "
3393
"Cannot create with new secondary:%s again!",
3394
volinfo->volname, secondary1.old_sechost, secondary_vol,
3399
/* There is a remote possibility that secondary_host can be NULL when
3400
control reaches here. Add a check so we wouldn't crash in next
3402
if (!secondary_host)
3405
/* Now, check whether session is already started.If so, warn!*/
3406
is_different_secondaryhost = (strcmp(secondary_host,
3407
secondary1.old_sechost) != 0)
3411
if (strstr(secondary_url, "@")) {
3412
secondary_url_buf = gf_strdup(secondary_url);
3413
if (!secondary_url_buf) {
3414
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
3415
"Unable to allocate memory");
3419
secondary_user = strtok_r(secondary_url_buf, "@", &save_ptr);
3421
secondary_user = "root";
3422
is_different_username = (strcmp(secondary_user,
3423
secondary1.old_secuser) != 0)
3427
/* Do the check, only if different secondary host/secondary user */
3428
if (is_different_secondaryhost || is_different_username) {
3429
len = snprintf(old_confpath, sizeof(old_confpath),
3430
"%s/" GEOREP "/%s_%s_%s/gsyncd.conf", conf->workdir,
3431
volinfo->volname, secondary1.old_sechost,
3433
if ((len < 0) || (len >= sizeof(old_confpath))) {
3438
/* construct old secondary url with (old) secondary host */
3439
len = snprintf(old_secondary_url, sizeof(old_secondary_url),
3440
"%s::%s", secondary1.old_sechost, secondary_vol);
3441
if ((len < 0) || (len >= sizeof(old_secondary_url))) {
3446
ret = glusterd_check_gsync_running_local(
3447
volinfo->volname, old_secondary_url, old_confpath, &is_running);
3448
if (_gf_true == is_running) {
3449
(void)snprintf(errmsg, sizeof(errmsg),
3451
"-replication session between %s and %s"
3452
" is still active. Please stop the "
3453
"session and retry.",
3454
volinfo->volname, old_secondary_url);
3460
ret = dict_set_dynstr_with_alloc(dict, "old_secondaryhost",
3461
secondary1.old_sechost);
3463
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
3464
"Unable to set old_secondaryhost in the dict");
3468
ret = dict_set_int32(dict, "existing_session", _gf_true);
3470
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
3471
"Unable to set existing_session in the dict");
3474
} else if (ret == -2) {
3475
snprintf(errmsg, sizeof(errmsg),
3476
"get_secondaryhost_from_voluuid"
3477
" failed for %s::%s. Please check the glusterd logs.",
3478
secondary_host, secondary_vol);
3479
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_FORCE_CREATE_SESSION,
3480
"get_secondaryhost_from_voluuid failed %s %s!!", secondary_host,
3485
ret = glusterd_verify_gsyncd_spawn(volinfo->volname, secondary);
3487
snprintf(errmsg, sizeof(errmsg), "Unable to spawn gsyncd.");
3488
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_SPAWN_FAILED, "%s",
3496
if (ret && errmsg[0] != '\0')
3497
*op_errstr = gf_strdup(errmsg);
3499
if (secondary_url_buf)
3500
GF_FREE(secondary_url_buf);
3505
/* pre-condition check for geo-rep pause/resume.
3506
* Return: 0 on success
3507
* -1 on any check failed.
3510
gd_pause_resume_validation(int type, glusterd_volinfo_t *volinfo,
3511
char *secondary, char *statefile, char **op_errstr)
3514
char errmsg[PATH_MAX] = {
3517
char monitor_status[NAME_MAX] = {
3522
GF_ASSERT(secondary);
3523
GF_ASSERT(statefile);
3524
GF_ASSERT(op_errstr);
3526
ret = glusterd_gsync_read_frm_status(statefile, monitor_status,
3527
sizeof(monitor_status));
3529
snprintf(errmsg, sizeof(errmsg),
3530
"Pause check Failed:"
3531
" Geo-rep session is not setup");
3536
if (type == GF_GSYNC_OPTION_TYPE_PAUSE &&
3537
strstr(monitor_status, "Paused")) {
3538
snprintf(errmsg, sizeof(errmsg),
3540
" session between %s and %s already Paused.",
3541
volinfo->volname, secondary);
3545
if (type == GF_GSYNC_OPTION_TYPE_RESUME &&
3546
!strstr(monitor_status, "Paused")) {
3547
snprintf(errmsg, sizeof(errmsg),
3549
" session between %s and %s is not Paused.",
3550
volinfo->volname, secondary);
3556
if (ret && (errmsg[0] != '\0')) {
3557
*op_errstr = gf_strdup(errmsg);
3563
glusterd_op_stage_gsync_set(dict_t *dict, char **op_errstr)
3567
char *volname = NULL;
3568
char *secondary = NULL;
3569
char *secondary_url = NULL;
3570
char *secondary_host = NULL;
3571
char *secondary_vol = NULL;
3572
char *down_peerstr = NULL;
3573
char *statefile = NULL;
3574
char statefiledir[PATH_MAX] = {
3577
char *statedir = NULL;
3578
char *path_list = NULL;
3579
char *conf_path = NULL;
3580
glusterd_volinfo_t *volinfo = NULL;
3581
char errmsg[PATH_MAX] = {
3585
gf_boolean_t is_force = 0;
3586
gf_boolean_t is_running = _gf_false;
3587
gf_boolean_t is_template_in_use = _gf_false;
3589
char uuid_str[64] = {0};
3590
char *host_uuid = NULL;
3591
xlator_t *this = THIS;
3592
glusterd_conf_t *conf = NULL;
3593
struct stat stbuf = {
3597
conf = this->private;
3600
ret = dict_get_int32(dict, "type", &type);
3602
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
3603
"command type not found");
3604
*op_errstr = gf_strdup("command unsuccessful");
3608
if (type == GF_GSYNC_OPTION_TYPE_STATUS) {
3609
ret = glusterd_verify_gsync_status_opts(dict, op_errstr);
3613
ret = glusterd_op_gsync_args_get(dict, op_errstr, &volname, &secondary,
3618
uuid_utoa_r(MY_UUID, uuid_str);
3620
if (conf->op_version < 2) {
3621
snprintf(errmsg, sizeof(errmsg),
3622
"One or more nodes do not"
3623
" support the required op version.");
3628
ret = glusterd_volinfo_find(volname, &volinfo);
3630
snprintf(errmsg, sizeof(errmsg),
3631
"Volume name %s does not"
3637
ret = glusterd_get_secondary_details_confpath(
3638
volinfo, dict, &secondary_url, &secondary_host, &secondary_vol,
3639
&conf_path, op_errstr);
3641
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARYINFO_FETCH_ERROR,
3642
"Unable to fetch secondary or confpath details.");
3647
is_force = dict_get_str_boolean(dict, "force", _gf_false);
3649
ret = glusterd_get_statefile_name(volinfo, secondary, conf_path, &statefile,
3650
&is_template_in_use);
3652
if (!strstr(secondary, "::")) {
3653
snprintf(errmsg, sizeof(errmsg), "%s is not a valid secondary url.",
3658
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_URL_INVALID,
3659
"state_file entry missing in config file (%s)", conf_path);
3661
if ((type == GF_GSYNC_OPTION_TYPE_STOP) && is_force) {
3662
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_STOP_FORCE,
3664
"force to bypass missing statefile "
3665
"entry in config file (%s), and "
3673
ret = dict_set_str(dict, "statefile", statefile);
3675
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
3676
"Unable to store statefile path");
3681
/* Allowing stop force to bypass the statefile check
3682
* as this command acts as a fail safe method to stop geo-rep
3684
if (!((type == GF_GSYNC_OPTION_TYPE_STOP) && is_force)) {
3685
/* check session directory as statefile may not present
3687
if (snprintf(statefiledir, sizeof(statefiledir), "%s", statefile) >=
3688
sizeof(statefiledir)) {
3689
snprintf(errmsg, sizeof(errmsg), "Failed copying statefiledir");
3693
statedir = dirname(statefiledir);
3695
ret = sys_lstat(statedir, &stbuf);
3697
snprintf(errmsg, sizeof(errmsg),
3699
" session between %s and %s does not exist.",
3700
volinfo->volname, secondary);
3701
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
3702
"%s. statefile = %s", errmsg, statefile);
3708
/* Check if all peers that are a part of the volume are up or not */
3709
if ((type == GF_GSYNC_OPTION_TYPE_DELETE) ||
3710
((type == GF_GSYNC_OPTION_TYPE_STOP) && !is_force) ||
3711
(type == GF_GSYNC_OPTION_TYPE_PAUSE) ||
3712
(type == GF_GSYNC_OPTION_TYPE_RESUME)) {
3713
if (!strcmp(uuid_str, host_uuid)) {
3714
ret = glusterd_are_vol_all_peers_up(volinfo, &conf->peers,
3716
if (ret == _gf_false) {
3717
snprintf(errmsg, sizeof(errmsg),
3719
" which is a part of %s volume, is"
3720
" down. Please bring up the peer and"
3722
down_peerstr, volinfo->volname);
3724
GF_FREE(down_peerstr);
3725
down_peerstr = NULL;
3732
case GF_GSYNC_OPTION_TYPE_START:
3733
if (is_template_in_use) {
3734
snprintf(errmsg, sizeof(errmsg),
3736
"missing in the config file(%s).",
3742
ret = glusterd_op_verify_gsync_start_options(
3743
volinfo, secondary, conf_path, statefile, op_errstr, is_force);
3746
ctx = glusterd_op_get_ctx();
3748
/* gsyncd does a fuse mount to start
3749
* the geo-rep session */
3750
if (!glusterd_is_fuse_available()) {
3751
gf_msg("glusterd", GF_LOG_ERROR, errno,
3752
GD_MSG_GEO_REP_START_FAILED,
3754
"to open /dev/fuse (%s), "
3755
"geo-replication start failed",
3757
snprintf(errmsg, sizeof(errmsg), "fuse unavailable");
3764
case GF_GSYNC_OPTION_TYPE_STOP:
3766
if (is_template_in_use) {
3767
snprintf(errmsg, sizeof(errmsg),
3768
"state-file entry missing in "
3769
"the config file(%s).",
3775
ret = glusterd_op_verify_gsync_running(volinfo, secondary,
3776
conf_path, op_errstr);
3778
ret = glusterd_get_local_brickpaths(volinfo, &path_list);
3779
if (!path_list && ret == -1)
3783
/* Check for geo-rep session is active or not for
3784
* configured user.*/
3785
ret = glusterd_gsync_get_uuid(secondary, volinfo, uuid);
3787
snprintf(errmsg, sizeof(errmsg),
3788
"Geo-replication session between %s "
3789
"and %s does not exist.",
3790
volinfo->volname, secondary);
3797
case GF_GSYNC_OPTION_TYPE_PAUSE:
3798
case GF_GSYNC_OPTION_TYPE_RESUME:
3799
if (is_template_in_use) {
3800
snprintf(errmsg, sizeof(errmsg),
3801
"state-file entry missing in "
3802
"the config file(%s).",
3808
ret = glusterd_op_verify_gsync_running(volinfo, secondary,
3809
conf_path, op_errstr);
3811
ret = glusterd_get_local_brickpaths(volinfo, &path_list);
3812
if (!path_list && ret == -1)
3816
/* Check for geo-rep session is active or not
3817
* for configured user.*/
3818
ret = glusterd_gsync_get_uuid(secondary, volinfo, uuid);
3820
snprintf(errmsg, sizeof(errmsg),
3822
" session between %s and %s does not exist.",
3823
volinfo->volname, secondary);
3829
ret = gd_pause_resume_validation(type, volinfo, secondary,
3830
statefile, op_errstr);
3832
ret = glusterd_get_local_brickpaths(volinfo, &path_list);
3833
if (!path_list && ret == -1)
3839
case GF_GSYNC_OPTION_TYPE_CONFIG:
3840
if (is_template_in_use) {
3841
snprintf(errmsg, sizeof(errmsg),
3843
"missing in the config file(%s).",
3849
ret = gsync_verify_config_options(dict, op_errstr, volname);
3853
case GF_GSYNC_OPTION_TYPE_DELETE:
3854
/* Check if the gsync session is still running
3855
* If so ask the user to stop geo-replication first.*/
3856
if (is_template_in_use) {
3857
snprintf(errmsg, sizeof(errmsg),
3859
"missing in the config file(%s).",
3865
ret = glusterd_gsync_get_uuid(secondary, volinfo, uuid);
3867
snprintf(errmsg, sizeof(errmsg),
3869
" session between %s and %s does not exist.",
3870
volinfo->volname, secondary);
3874
ret = glusterd_check_gsync_running_local(
3875
volinfo->volname, secondary, conf_path, &is_running);
3876
if (_gf_true == is_running) {
3877
snprintf(errmsg, sizeof(errmsg),
3879
" session between %s & %s is "
3880
"still active. Please stop the "
3881
"session and retry.",
3882
volinfo->volname, secondary);
3888
ret = glusterd_verify_gsyncd_spawn(volinfo->volname, secondary);
3890
snprintf(errmsg, sizeof(errmsg), "Unable to spawn gsyncd");
3901
if (ret && errmsg[0] != '\0') {
3902
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR, "%s", errmsg);
3903
*op_errstr = gf_strdup(errmsg);
3906
gf_msg_debug(this->name, 0, "Returning %d", ret);
3911
gd_pause_or_resume_gsync(dict_t *dict, char *primary, char *secondary,
3912
char *secondary_host, char *secondary_vol,
3913
char *conf_path, char **op_errstr,
3914
gf_boolean_t is_pause)
3919
char pidfile[PATH_MAX] = {
3922
char errmsg[PATH_MAX] = "";
3926
gf_boolean_t is_template_in_use = _gf_false;
3927
char monitor_status[NAME_MAX] = {
3930
char *statefile = NULL;
3931
xlator_t *this = THIS;
3935
GF_ASSERT(secondary);
3936
GF_ASSERT(secondary_host);
3937
GF_ASSERT(secondary_vol);
3938
GF_ASSERT(conf_path);
3940
pfd = gsyncd_getpidfile(primary, secondary, pidfile, conf_path,
3941
&is_template_in_use);
3943
snprintf(errmsg, sizeof(errmsg),
3944
"pid-file entry mising in config file and "
3945
"template config file.");
3946
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PIDFILE_NOT_FOUND, "%s",
3948
*op_errstr = gf_strdup(errmsg);
3953
if (gsync_status_byfd(pfd) == -1) {
3954
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR,
3955
"gsyncd b/w %s & %s is not running", primary, secondary);
3956
/* monitor gsyncd already dead */
3963
/* Prepare to update status file*/
3964
ret = dict_get_str(dict, "statefile", &statefile);
3966
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
3967
"Pause/Resume Failed: Unable to fetch statefile path");
3970
ret = glusterd_gsync_read_frm_status(statefile, monitor_status,
3971
sizeof(monitor_status));
3973
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STAT_FILE_READ_FAILED,
3974
"Pause/Resume Failed: "
3975
"Unable to read status file for %s(primary)"
3977
primary, secondary);
3981
ret = sys_read(pfd, buf, sizeof(buf) - 1);
3984
pid = strtol(buf, NULL, 10);
3986
ret = kill(-pid, SIGSTOP);
3988
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_PID_KILL_FAIL,
3990
" to pause gsyncd. Error: %s",
3994
/*On pause force, if status is already paused
3995
do not update status again*/
3996
if (strstr(monitor_status, "Paused"))
3999
ret = glusterd_create_status_file(
4000
primary, secondary, secondary_host, secondary_vol, "Paused");
4002
gf_msg(this->name, GF_LOG_ERROR, 0,
4003
GD_MSG_UPDATE_STATEFILE_FAILED,
4004
"Unable to update state_file."
4007
/* If status cannot be updated resume back */
4008
if (kill(-pid, SIGCONT)) {
4009
snprintf(errmsg, sizeof(errmsg),
4010
"Pause successful but could "
4011
"not update status file. "
4012
"Please use 'resume force' to"
4013
" resume back and retry pause"
4014
" to reflect in status");
4015
gf_msg(this->name, GF_LOG_ERROR, errno,
4016
GD_MSG_PID_KILL_FAIL,
4017
"Resume back Failed. Error:"
4020
*op_errstr = gf_strdup(errmsg);
4025
ret = glusterd_create_status_file(
4026
primary, secondary, secondary_host, secondary_vol, "Started");
4028
gf_msg(this->name, GF_LOG_ERROR, 0,
4029
GD_MSG_UPDATE_STATEFILE_FAILED,
4030
"Resume Failed: Unable to update "
4031
"state_file. Error : %s",
4035
ret = kill(-pid, SIGCONT);
4037
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_PID_KILL_FAIL,
4038
"Resumed Failed: Unable to send"
4039
" SIGCONT. Error: %s",
4041
/* Process can't be resumed, update status
4042
* back to paused. */
4043
ret = glusterd_create_status_file(primary, secondary,
4044
secondary_host, secondary_vol,
4047
snprintf(errmsg, sizeof(errmsg),
4048
"Resume failed!!! Status "
4049
"inconsistent. Please use "
4050
"'resume force' to resume and"
4051
" reach consistent state");
4052
gf_msg(this->name, GF_LOG_ERROR, 0,
4053
GD_MSG_STATUS_UPDATE_FAILED,
4054
"Updating status back to paused"
4055
" Failed. Error: %s",
4057
*op_errstr = gf_strdup(errmsg);
4067
/* coverity[INTEGER_OVERFLOW] */
4072
stop_gsync(char *primary, char *secondary, char **msg, char *conf_path,
4073
char **op_errstr, gf_boolean_t is_force)
4078
char pidfile[PATH_MAX] = {
4081
char errmsg[PATH_MAX] = "";
4086
gf_boolean_t is_template_in_use = _gf_false;
4087
xlator_t *this = THIS;
4089
pfd = gsyncd_getpidfile(primary, secondary, pidfile, conf_path,
4090
&is_template_in_use);
4092
snprintf(errmsg, sizeof(errmsg) - 1,
4093
"pid-file entry mising in config file and "
4094
"template config file.");
4095
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PIDFILE_NOT_FOUND, "%s",
4097
*op_errstr = gf_strdup(errmsg);
4101
if (gsync_status_byfd(pfd) == -1 && !is_force) {
4102
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR,
4103
"gsyncd b/w %s & %s is not running", primary, secondary);
4104
/* monitor gsyncd already dead */
4111
ret = sys_read(pfd, buf, sizeof(buf) - 1);
4114
pid = strtol(buf, NULL, 10);
4115
ret = kill(-pid, SIGTERM);
4116
if (ret && !is_force) {
4117
gf_msg(this->name, GF_LOG_WARNING, errno, GD_MSG_PID_KILL_FAIL,
4118
"failed to kill gsyncd");
4121
for (i = 0; i < 20; i++) {
4122
if (gsync_status_byfd(pfd) == -1) {
4123
/* monitor gsyncd is dead but worker may
4124
* still be alive, give some more time
4125
* before SIGKILL (hack)
4127
gf_nanosleep(50000 * GF_US_IN_NS);
4130
gf_nanosleep(50000 * GF_US_IN_NS);
4132
kill(-pid, SIGKILL);
4133
sys_unlink(pidfile);
4139
/* coverity[INTEGER_OVERFLOW] */
4144
* glusterd_gsync_op_already_set:
4145
* This function checks whether the op_value is same as in the
4149
* 0 : op_value matches the conf file.
4150
* 1 : op_value does not matches the conf file or op_param not
4151
* found in conf file.
4156
glusterd_gsync_op_already_set(char *primary, char *secondary, char *conf_path,
4157
char *op_name, char *op_value)
4159
dict_t *confd = NULL;
4160
char *op_val_buf = NULL;
4161
int32_t op_val_conf = 0;
4162
int32_t op_val_cli = 0;
4164
gf_boolean_t is_bool = _gf_true;
4165
xlator_t *this = THIS;
4169
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL,
4170
"Not able to create dict.");
4174
ret = glusterd_gsync_get_config(primary, secondary, conf_path, confd);
4176
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_CONFIG_INFO_FAILED,
4177
"Unable to get configuration data for %s(primary), "
4179
primary, secondary);
4183
ret = dict_get_param(confd, op_name, &op_val_buf);
4185
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4186
"Unable to get op_value for %s(primary), %s(secondary). "
4187
"Please check gsync config file.",
4188
primary, secondary);
4193
gf_msg_debug(this->name, 0, "val_cli:%s val_conf:%s", op_value,
4196
if (!strcmp(op_val_buf, "true") || !strcmp(op_val_buf, "1") ||
4197
!strcmp(op_val_buf, "yes")) {
4199
} else if (!strcmp(op_val_buf, "false") || !strcmp(op_val_buf, "0") ||
4200
!strcmp(op_val_buf, "no")) {
4203
is_bool = _gf_false;
4207
if (op_value && (!strcmp(op_value, "true") || !strcmp(op_value, "1") ||
4208
!strcmp(op_value, "yes"))) {
4214
if (op_val_cli == op_val_conf) {
4219
if (op_value && !strcmp(op_val_buf, op_value)) {
4233
glusterd_gsync_configure(glusterd_volinfo_t *volinfo, char *secondary,
4234
char *path_list, dict_t *dict, dict_t *resp_dict,
4238
char *op_name = NULL;
4239
char *op_value = NULL;
4243
glusterd_conf_t *priv = NULL;
4245
char *primary = NULL;
4246
char *conf_path = NULL;
4247
char *secondary_host = NULL;
4248
char *secondary_vol = NULL;
4249
struct stat stbuf = {
4252
gf_boolean_t restart_required = _gf_true;
4253
char **resopt = NULL;
4254
gf_boolean_t op_already_set = _gf_false;
4255
xlator_t *this = THIS;
4257
GF_ASSERT(secondary);
4258
GF_ASSERT(op_errstr);
4260
GF_ASSERT(resp_dict);
4262
ret = dict_get_str(dict, "subop", &subop);
4266
if (strcmp(subop, "get") == 0 || strcmp(subop, "get-all") == 0) {
4267
/* deferred to cli */
4268
gf_msg_debug(this->name, 0, "Returning 0");
4272
ret = dict_get_str(dict, "op_name", &op_name);
4276
if (strtail(subop, "set")) {
4277
ret = dict_get_str(dict, "op_value", &op_value);
4282
priv = THIS->private;
4284
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
4285
"priv of glusterd not present");
4286
*op_errstr = gf_strdup("glusterd defunct");
4290
ret = dict_get_str(dict, "conf_path", &conf_path);
4292
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4293
"Unable to fetch conf file path.");
4299
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "-c", NULL);
4300
runner_argprintf(&runner, "%s", conf_path);
4301
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
4303
primary = volinfo->volname;
4304
runner_argprintf(&runner, ":%s", primary);
4306
runner_add_arg(&runner, secondary);
4307
runner_argprintf(&runner, "--config-%s", subop);
4308
runner_add_arg(&runner, op_name);
4310
runner_argprintf(&runner, "--value=%s", op_value);
4313
if (strcmp(op_name, "checkpoint") != 0 && strtail(subop, "set")) {
4314
ret = glusterd_gsync_op_already_set(primary, secondary, conf_path,
4317
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_GSYNCD_OP_SET_FAILED,
4318
"glusterd_gsync_op_already_set failed.");
4319
gf_asprintf(op_errstr,
4321
" config-%s failed for "
4323
subop, primary, secondary);
4327
gf_msg_debug(this->name, 0, "op_value is already set");
4328
op_already_set = _gf_true;
4333
synclock_unlock(&priv->big_lock);
4334
ret = runner_run(&runner);
4335
synclock_lock(&priv->big_lock);
4337
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_GSYNCD_ERROR,
4338
"gsyncd failed to %s %s option for "
4340
subop, op_name, primary, secondary);
4342
gf_asprintf(op_errstr, GEOREP " config-%s failed for %s %s", subop,
4343
primary, secondary);
4348
if ((!strcmp(op_name, "state_file")) && (op_value)) {
4349
ret = sys_lstat(op_value, &stbuf);
4351
ret = dict_get_str(dict, "secondary_host", &secondary_host);
4353
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4354
"Unable to fetch secondary host.");
4358
ret = dict_get_str(dict, "secondary_vol", &secondary_vol);
4360
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4361
"Unable to fetch secondary volume name.");
4365
ret = glusterd_create_status_file(volinfo->volname, secondary,
4366
secondary_host, secondary_vol,
4369
if (ret || sys_lstat(op_value, &stbuf)) {
4370
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_FILE_OP_FAILED,
4372
"create %s. Error : %s",
4373
op_value, strerror(errno));
4381
gf_asprintf(op_errstr, "config-%s successful", subop);
4384
if (!ret && volinfo && !op_already_set) {
4385
for (resopt = gsync_no_restart_opts; *resopt; resopt++) {
4386
restart_required = _gf_true;
4387
if (!strcmp((*resopt), op_name)) {
4388
restart_required = _gf_false;
4393
if (restart_required) {
4394
ret = glusterd_check_restart_gsync_session(
4395
volinfo, secondary, resp_dict, path_list, conf_path, 0);
4397
*op_errstr = gf_strdup("internal error");
4401
gf_msg_debug(this->name, 0, "Returning %d", ret);
4406
glusterd_gsync_read_frm_status(char *path, char *buf, size_t blen)
4410
xlator_t *this = THIS;
4414
status_fd = open(path, O_RDONLY);
4415
if (status_fd == -1) {
4416
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FILE_OP_FAILED,
4417
"Unable to read gsyncd status file %s", path);
4420
ret = sys_read(status_fd, buf, blen - 1);
4424
size_t len = strnlen(buf, ret);
4425
/* Ensure there is a NUL byte and that it's not the first. */
4426
if (len == 0 || len == blen - 1) {
4429
char *p = buf + len - 1;
4433
} else if (ret == 0)
4434
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR,
4435
"Status file of gsyncd is empty");
4437
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR,
4438
"Status file of gsyncd is corrupt");
4440
sys_close(status_fd);
4445
dict_get_param(dict_t *dict, char *key, char **param)
4452
if (dict_get_str(dict, key, param) == 0)
4455
dk = gf_strdup(key);
4459
s = strpbrk(dk, "-_");
4464
x = (*s == '-') ? '_' : '-';
4466
while ((s = strpbrk(s, "-_")))
4469
ret = dict_get_str(dict, dk, param);
4476
glusterd_fetch_values_from_config(char *primary, char *secondary,
4477
char *confpath, dict_t *confd,
4479
char **georep_session_wrkng_dir,
4483
xlator_t *this = THIS;
4485
ret = glusterd_gsync_get_config(primary, secondary, confpath, confd);
4487
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_CONFIG_INFO_FAILED,
4488
"Unable to get configuration data for %s(primary), "
4490
primary, secondary);
4495
ret = dict_get_param(confd, "state_file", statefile);
4497
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4498
"Unable to get state_file's name "
4499
"for %s(primary), %s(secondary). "
4500
"Please check gsync config file.",
4501
primary, secondary);
4506
if (georep_session_wrkng_dir) {
4507
ret = dict_get_param(confd, "georep_session_working_dir",
4508
georep_session_wrkng_dir);
4510
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4511
"Unable to get geo-rep session's "
4512
"working directory name for %s(primary), "
4513
"%s(secondary). Please check gsync config file.",
4514
primary, secondary);
4520
ret = dict_get_param(confd, "state_socket_unencoded", socketfile);
4522
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
4523
"Unable to get socket file's name "
4524
"for %s(primary), %s(secondary). "
4525
"Please check gsync config file.",
4526
primary, secondary);
4533
gf_msg_debug(this->name, 0, "Returning %d", ret);
4538
glusterd_read_status_file(glusterd_volinfo_t *volinfo, char *secondary,
4539
char *conf_path, dict_t *dict, char *node)
4541
char temp_conf_path[PATH_MAX] = "";
4542
char *working_conf_path = NULL;
4543
char *georep_session_wrkng_dir = NULL;
4544
char *primary = NULL;
4545
char sts_val_name[1024] = "";
4546
char monitor_status[NAME_MAX] = "";
4547
char *statefile = NULL;
4548
char *socketfile = NULL;
4549
dict_t *confd = NULL;
4550
char *secondarykey = NULL;
4551
char *secondaryentry = NULL;
4552
char *secondaryuser = NULL;
4553
char *saveptr = NULL;
4555
char *temp_inp = NULL;
4556
char *brick_host_uuid = NULL;
4557
int brick_host_uuid_length = 0;
4558
int gsync_count = 0;
4560
glusterd_brickinfo_t *brickinfo = NULL;
4561
gf_gsync_status_t *sts_val = NULL;
4562
gf_boolean_t is_template_in_use = _gf_false;
4563
glusterd_conf_t *priv = NULL;
4564
struct stat stbuf = {
4567
xlator_t *this = THIS;
4570
priv = this->private;
4573
GF_ASSERT(conf_path);
4575
primary = volinfo->volname;
4579
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL,
4580
"Not able to create dict.");
4585
len = snprintf(temp_conf_path, sizeof(temp_conf_path),
4586
"%s/" GSYNC_CONF_TEMPLATE, priv->workdir);
4587
if ((len < 0) || (len >= sizeof(temp_conf_path))) {
4592
ret = sys_lstat(conf_path, &stbuf);
4594
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_CONFIG_INFO,
4595
"Using passed config template(%s).", conf_path);
4596
working_conf_path = conf_path;
4598
gf_msg(this->name, GF_LOG_WARNING, ENOENT, GD_MSG_FILE_OP_FAILED,
4599
"Config file (%s) missing. Looking for template "
4601
conf_path, temp_conf_path);
4602
ret = sys_lstat(temp_conf_path, &stbuf);
4604
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
4606
"config file (%s) missing.",
4610
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DEFAULT_TEMP_CONFIG,
4611
"Using default config template(%s).", temp_conf_path);
4612
working_conf_path = temp_conf_path;
4613
is_template_in_use = _gf_true;
4617
ret = glusterd_fetch_values_from_config(
4618
primary, secondary, working_conf_path, confd, &statefile,
4619
&georep_session_wrkng_dir, &socketfile);
4621
if (is_template_in_use == _gf_false) {
4622
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FETCH_CONFIG_VAL_FAILED,
4623
"Unable to fetch config values "
4624
"for %s(primary), %s(secondary). "
4625
"Trying default config template",
4626
primary, secondary);
4627
working_conf_path = temp_conf_path;
4628
is_template_in_use = _gf_true;
4631
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FETCH_CONFIG_VAL_FAILED,
4633
"fetch config values for %s(primary), "
4635
primary, secondary);
4640
ret = glusterd_gsync_read_frm_status(statefile, monitor_status,
4641
sizeof(monitor_status));
4643
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STAT_FILE_READ_FAILED,
4644
"Unable to read the status file for %s(primary), "
4645
"%s(secondary) statefile: %s",
4646
primary, secondary, statefile);
4647
snprintf(monitor_status, sizeof(monitor_status), "defunct");
4650
ret = dict_get_int32(dict, "gsync-count", &gsync_count);
4654
cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list)
4656
if (gf_uuid_compare(brickinfo->uuid, MY_UUID))
4659
sts_val = GF_CALLOC(1, sizeof(gf_gsync_status_t),
4660
gf_common_mt_gsync_status_t);
4662
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
4668
ret = glusterd_get_secondary(volinfo, secondary, &secondarykey);
4673
memcpy(sts_val->secondarykey, secondarykey, strlen(secondarykey));
4674
sts_val->secondarykey[strlen(secondarykey)] = '\0';
4676
/* Primary Volume */
4677
memcpy(sts_val->primary, primary, strlen(primary));
4678
sts_val->primary[strlen(primary)] = '\0';
4680
/* Primary Brick Node */
4681
memcpy(sts_val->node, brickinfo->hostname, strlen(brickinfo->hostname));
4682
sts_val->node[strlen(brickinfo->hostname)] = '\0';
4684
/* Primary Brick Path */
4685
memcpy(sts_val->brick, brickinfo->path, strlen(brickinfo->path));
4686
sts_val->brick[strlen(brickinfo->path)] = '\0';
4688
/* Brick Host UUID */
4689
brick_host_uuid = uuid_utoa(brickinfo->uuid);
4690
brick_host_uuid_length = strlen(brick_host_uuid);
4691
memcpy(sts_val->brick_host_uuid, brick_host_uuid,
4692
brick_host_uuid_length);
4693
sts_val->brick_host_uuid[brick_host_uuid_length] = '\0';
4696
memcpy(sts_val->secondary, secondary, strlen(secondary));
4697
sts_val->secondary[strlen(secondary)] = '\0';
4699
snprintf(sts_val->secondary_node, sizeof(sts_val->secondary_node),
4702
snprintf(sts_val->worker_status, sizeof(sts_val->worker_status), "N/A");
4704
snprintf(sts_val->crawl_status, sizeof(sts_val->crawl_status), "N/A");
4706
snprintf(sts_val->last_synced, sizeof(sts_val->last_synced), "N/A");
4708
snprintf(sts_val->last_synced_utc, sizeof(sts_val->last_synced_utc),
4711
snprintf(sts_val->entry, sizeof(sts_val->entry), "N/A");
4713
snprintf(sts_val->data, sizeof(sts_val->data), "N/A");
4715
snprintf(sts_val->meta, sizeof(sts_val->meta), "N/A");
4717
snprintf(sts_val->failures, sizeof(sts_val->failures), "N/A");
4719
snprintf(sts_val->checkpoint_time, sizeof(sts_val->checkpoint_time),
4722
snprintf(sts_val->checkpoint_time_utc,
4723
sizeof(sts_val->checkpoint_time_utc), "N/A");
4725
snprintf(sts_val->checkpoint_completed,
4726
sizeof(sts_val->checkpoint_completed), "N/A");
4728
snprintf(sts_val->checkpoint_completion_time,
4729
sizeof(sts_val->checkpoint_completion_time), "N/A");
4731
snprintf(sts_val->checkpoint_completion_time_utc,
4732
sizeof(sts_val->checkpoint_completion_time_utc), "N/A");
4734
/* Get all the other values from Gsyncd */
4735
ret = glusterd_gsync_get_status(primary, secondary, conf_path,
4736
brickinfo->path, sts_val);
4739
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_STATUS_DATA_FAIL,
4740
"Unable to get status data "
4741
"for %s(primary), %s(secondary), %s(brick)",
4742
primary, secondary, brickinfo->path);
4747
if (is_template_in_use) {
4748
snprintf(sts_val->worker_status, sizeof(sts_val->worker_status),
4749
"Config Corrupted");
4752
ret = dict_get_str(volinfo->gsync_secondaries, secondarykey,
4759
memcpy(sts_val->session_secondary, secondaryentry,
4760
strlen(secondaryentry));
4761
sts_val->session_secondary[strlen(secondaryentry)] = '\0';
4763
temp_inp = gf_strdup(secondaryentry);
4767
if (strstr(temp_inp, "@") == NULL) {
4768
secondaryuser = "root";
4770
temp = strtok_r(temp_inp, "//", &saveptr);
4771
temp = strtok_r(NULL, "/", &saveptr);
4772
secondaryuser = strtok_r(temp, "@", &saveptr);
4774
memcpy(sts_val->secondary_user, secondaryuser, strlen(secondaryuser));
4775
sts_val->secondary_user[strlen(secondaryuser)] = '\0';
4777
snprintf(sts_val_name, sizeof(sts_val_name), "status_value%d",
4779
ret = dict_set_bin(dict, sts_val_name, sts_val,
4780
sizeof(gf_gsync_status_t));
4790
ret = dict_set_int32(dict, "gsync-count", gsync_count);
4801
glusterd_check_restart_gsync_session(glusterd_volinfo_t *volinfo,
4802
char *secondary, dict_t *resp_dict,
4803
char *path_list, char *conf_path,
4804
gf_boolean_t is_force)
4807
char *status_msg = NULL;
4808
gf_boolean_t is_running = _gf_false;
4809
char *op_errstr = NULL;
4811
xlator_t *this = THIS;
4814
GF_ASSERT(secondary);
4818
ret = glusterd_check_gsync_running_local(volinfo->volname, secondary,
4819
conf_path, &is_running);
4820
if (!ret && (_gf_true != is_running))
4821
/* gsynd not running, nothing to do */
4824
ret = stop_gsync(volinfo->volname, secondary, &status_msg, conf_path,
4825
&op_errstr, is_force);
4826
if (ret == 0 && status_msg)
4827
ret = dict_set_str(resp_dict, "gsync-status", status_msg);
4829
dict_del(volinfo->gsync_active_secondaries, key);
4830
ret = glusterd_start_gsync(volinfo, secondary, path_list, conf_path,
4831
uuid_utoa(MY_UUID), NULL, _gf_false);
4833
/* Add secondary to the dict indicating geo-rep session is
4835
ret = dict_set_dynstr_with_alloc(volinfo->gsync_active_secondaries,
4838
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
4840
" key:%s value:running in dict. But "
4841
"the config succeeded.",
4849
gf_msg_debug(this->name, 0, "Returning %d", ret);
4856
glusterd_marker_changelog_create_volfile(glusterd_volinfo_t *volinfo)
4860
ret = glusterd_create_volfiles_and_notify_services(volinfo);
4862
gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL,
4863
"Unable to create volfile for setting of marker "
4864
"while '" GEOREP " start'");
4869
ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT);
4873
if (GLUSTERD_STATUS_STARTED == volinfo->status) {
4874
ret = glusterd_svcs_manager(volinfo);
4883
glusterd_set_gsync_knob(glusterd_volinfo_t *volinfo, char *key, int *vc)
4886
int conf_enabled = _gf_false;
4887
xlator_t *this = THIS;
4889
conf_enabled = glusterd_volinfo_get_boolean(volinfo, key);
4890
if (conf_enabled == -1) {
4891
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GET_KEY_FAILED,
4892
"failed to get key %s from volinfo", key);
4897
if (conf_enabled == _gf_false) {
4899
ret = glusterd_gsync_volinfo_dict_set(volinfo, key, "on");
4903
gf_msg_debug(this->name, 0, "Returning %d", ret);
4908
glusterd_set_gsync_confs(glusterd_volinfo_t *volinfo)
4911
int volfile_changed = 0;
4913
ret = glusterd_set_gsync_knob(volinfo, VKEY_MARKER_XTIME, &volfile_changed);
4918
* enable ignore-pid-check blindly as it could be needed for
4921
ret = glusterd_set_gsync_knob(volinfo, VKEY_MARKER_XTIME_FORCE,
4926
ret = glusterd_set_gsync_knob(volinfo, VKEY_CHANGELOG, &volfile_changed);
4930
if (volfile_changed)
4931
ret = glusterd_marker_changelog_create_volfile(volinfo);
4938
glusterd_get_gsync_status_mst_slv(glusterd_volinfo_t *volinfo, char *secondary,
4939
char *conf_path, dict_t *rsp_dict, char *node)
4941
char *statefile = NULL;
4946
gf_boolean_t is_template_in_use = _gf_false;
4947
struct stat stbuf = {
4950
xlator_t *this = THIS;
4953
GF_ASSERT(secondary);
4955
ret = glusterd_gsync_get_uuid(secondary, volinfo, uuid);
4957
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_SESSION_INACTIVE,
4958
"geo-replication status %s %s : session is not "
4960
volinfo->volname, secondary);
4962
ret = glusterd_get_statefile_name(volinfo, secondary, conf_path,
4963
&statefile, &is_template_in_use);
4965
if (!strstr(secondary, "::"))
4966
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_SECONDARY_URL_INVALID,
4967
"%s is not a valid secondary url.", secondary);
4969
gf_msg(this->name, GF_LOG_INFO, 0,
4970
GD_MSG_GET_STATEFILE_NAME_FAILED,
4971
"Unable to get statefile's name");
4976
ret = sys_lstat(statefile, &stbuf);
4978
gf_msg(this->name, GF_LOG_INFO, ENOENT, GD_MSG_FILE_OP_FAILED,
4979
"%s statefile not present.", statefile);
4985
ret = glusterd_read_status_file(volinfo, secondary, conf_path, rsp_dict,
4991
gf_msg_debug(this->name, 0, "Returning with %d", ret);
4996
glusterd_get_gsync_status_mst(glusterd_volinfo_t *volinfo, dict_t *rsp_dict,
4999
glusterd_gsync_status_temp_t param = {
5005
param.rsp_dict = rsp_dict;
5006
param.volinfo = volinfo;
5008
dict_foreach(volinfo->gsync_secondaries, _get_status_mst_slv, ¶m);
5014
glusterd_get_gsync_status_all(dict_t *rsp_dict, char *node)
5017
glusterd_conf_t *priv = NULL;
5018
glusterd_volinfo_t *volinfo = NULL;
5019
xlator_t *this = THIS;
5021
priv = this->private;
5025
cds_list_for_each_entry(volinfo, &priv->volumes, vol_list)
5027
ret = glusterd_get_gsync_status_mst(volinfo, rsp_dict, node);
5033
gf_msg_debug(this->name, 0, "Returning with %d", ret);
5038
glusterd_get_gsync_status(dict_t *dict, char **op_errstr, dict_t *rsp_dict)
5040
char *secondary = NULL;
5041
char *volname = NULL;
5042
char *conf_path = NULL;
5043
char errmsg[PATH_MAX] = {
5046
glusterd_volinfo_t *volinfo = NULL;
5048
char *my_hostname = gf_gethostname();
5049
xlator_t *this = THIS;
5051
ret = dict_get_str(dict, "primary", &volname);
5053
ret = glusterd_get_gsync_status_all(rsp_dict, my_hostname);
5057
ret = glusterd_volinfo_find(volname, &volinfo);
5059
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_VOL_NOT_FOUND,
5060
"volume name does not exist");
5061
snprintf(errmsg, sizeof(errmsg),
5062
"Volume name %s does not"
5065
*op_errstr = gf_strdup(errmsg);
5069
ret = dict_get_str(dict, "secondary", &secondary);
5071
ret = glusterd_get_gsync_status_mst(volinfo, rsp_dict, my_hostname);
5075
ret = dict_get_str(dict, "conf_path", &conf_path);
5077
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5078
"Unable to fetch conf file path.");
5082
ret = glusterd_get_gsync_status_mst_slv(volinfo, secondary, conf_path,
5083
rsp_dict, my_hostname);
5086
gf_msg_debug(this->name, 0, "Returning %d", ret);
5091
glusterd_gsync_delete(glusterd_volinfo_t *volinfo, char *secondary,
5092
char *secondary_host, char *secondary_vol,
5093
char *path_list, dict_t *dict, dict_t *resp_dict,
5100
glusterd_conf_t *priv = NULL;
5101
char *primary = NULL;
5102
char *gl_workdir = NULL;
5103
char geo_rep_dir[PATH_MAX] = "";
5104
char *conf_path = NULL;
5105
xlator_t *this = THIS;
5106
uint32_t reset_sync_time = _gf_false;
5108
GF_ASSERT(secondary);
5109
GF_ASSERT(secondary_host);
5110
GF_ASSERT(secondary_vol);
5111
GF_ASSERT(op_errstr);
5113
GF_ASSERT(resp_dict);
5115
priv = this->private;
5117
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
5118
"priv of glusterd not present");
5119
*op_errstr = gf_strdup("glusterd defunct");
5123
ret = dict_get_str(dict, "conf_path", &conf_path);
5125
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5126
"Unable to fetch conf file path.");
5130
gl_workdir = priv->workdir;
5133
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "--delete", "-c", NULL);
5134
runner_argprintf(&runner, "%s", conf_path);
5135
runner_argprintf(&runner, "--iprefix=%s", DATADIR);
5137
runner_argprintf(&runner, "--path-list=%s", path_list);
5139
ret = dict_get_uint32(dict, "reset-sync-time", &reset_sync_time);
5140
if (!ret && reset_sync_time) {
5141
runner_add_args(&runner, "--reset-sync-time", NULL);
5145
primary = volinfo->volname;
5146
runner_argprintf(&runner, ":%s", primary);
5148
runner_add_arg(&runner, secondary);
5149
runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
5150
synclock_unlock(&priv->big_lock);
5151
ret = runner_run(&runner);
5152
synclock_lock(&priv->big_lock);
5154
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SESSION_DEL_FAILED,
5155
"gsyncd failed to delete session info for %s and "
5157
primary, secondary);
5159
gf_asprintf(op_errstr,
5161
"delete session info for %s and %s peers",
5162
primary, secondary);
5167
ret = snprintf(geo_rep_dir, sizeof(geo_rep_dir) - 1,
5168
"%s/" GEOREP "/%s_%s_%s", gl_workdir, volinfo->volname,
5169
secondary_host, secondary_vol);
5170
geo_rep_dir[ret] = '\0';
5172
ret = sys_rmdir(geo_rep_dir);
5174
if (errno == ENOENT)
5175
gf_msg_debug(this->name, 0, "Geo Rep Dir(%s) Not Present.",
5178
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DIR_OP_FAILED,
5179
"Unable to delete Geo Rep Dir(%s). Error: %s", geo_rep_dir,
5187
gf_asprintf(op_errstr, "delete successful");
5190
gf_msg_debug(this->name, 0, "Returning %d", ret);
5195
glusterd_op_sys_exec(dict_t *dict, char **op_errstr, dict_t *rsp_dict)
5197
char buf[PATH_MAX] = "";
5198
char cmd_arg_name[PATH_MAX] = "";
5199
char output_name[PATH_MAX] = "";
5200
char errmsg[PATH_MAX] = "";
5203
char *command = NULL;
5204
char **cmd_args = NULL;
5207
int cmd_args_count = 0;
5208
int output_count = 0;
5209
glusterd_conf_t *priv = NULL;
5213
xlator_t *this = THIS;
5216
GF_ASSERT(op_errstr);
5217
GF_ASSERT(rsp_dict);
5219
priv = this->private;
5221
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
5222
"priv of glusterd not present");
5223
*op_errstr = gf_strdup("glusterd defunct");
5227
ret = dict_get_str(dict, "command", &command);
5229
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5230
"Unable to get command from dict");
5234
ret = dict_get_int32(dict, "cmd_args_count", &cmd_args_count);
5236
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DICT_GET_FAILED,
5237
"No cmd_args_count");
5239
if (cmd_args_count) {
5240
cmd_args = GF_CALLOC(cmd_args_count, sizeof(char *), gf_common_mt_char);
5242
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
5243
"Unable to calloc. Errno = %s", strerror(errno));
5247
for (i = 1; i <= cmd_args_count; i++) {
5248
snprintf(cmd_arg_name, sizeof(cmd_arg_name), "cmd_arg_%d", i);
5249
ret = dict_get_str(dict, cmd_arg_name, &cmd_args[i - 1]);
5251
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5261
runner_argprintf(&runner, GSYNCD_PREFIX "/peer_%s", command);
5262
for (i = 0; i < cmd_args_count; i++)
5263
runner_add_arg(&runner, cmd_args[i]);
5264
runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
5265
synclock_unlock(&priv->big_lock);
5266
ret = runner_start(&runner);
5268
snprintf(errmsg, sizeof(errmsg),
5270
"execute command. Error : %s",
5272
*op_errstr = gf_strdup(errmsg);
5273
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CMD_EXEC_FAIL, "%s", errmsg);
5275
synclock_lock(&priv->big_lock);
5280
ptr = fgets(buf, sizeof(buf), runner_chio(&runner, STDOUT_FILENO));
5282
ret = dict_get_int32(rsp_dict, "output_count", &output_count);
5287
snprintf(output_name, sizeof(output_name), "output_%d",
5289
if (buf[strlen(buf) - 1] == '\n')
5290
buf[strlen(buf) - 1] = '\0';
5291
bufp = gf_strdup(buf);
5293
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STRDUP_FAILED,
5294
"gf_strdup failed.");
5295
ret = dict_set_dynstr(rsp_dict, output_name, bufp);
5298
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5302
ret = dict_set_int32(rsp_dict, "output_count", output_count);
5304
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5310
ret = runner_end(&runner);
5312
snprintf(errmsg, sizeof(errmsg),
5316
*op_errstr = gf_strdup(errmsg);
5317
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNABLE_TO_END, "%s", errmsg);
5319
synclock_lock(&priv->big_lock);
5322
synclock_lock(&priv->big_lock);
5331
gf_msg_debug(this->name, 0, "Returning %d", ret);
5336
glusterd_op_copy_file(dict_t *dict, char **op_errstr)
5338
char abs_filename[PATH_MAX] = "";
5339
char errmsg[PATH_MAX] = "";
5340
char *filename = NULL;
5341
char *host_uuid = NULL;
5342
char uuid_str[64] = {0};
5343
char *contents = NULL;
5344
char buf[4096] = "";
5347
int bytes_writen = 0;
5349
int contents_size = -1;
5351
glusterd_conf_t *priv = NULL;
5352
struct stat stbuf = {
5355
gf_boolean_t free_contents = _gf_true;
5356
xlator_t *this = THIS;
5359
priv = this->private;
5361
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GLUSTERD_PRIV_NOT_FOUND,
5362
"priv of glusterd not present");
5363
*op_errstr = gf_strdup("glusterd defunct");
5367
ret = dict_get_str(dict, "host-uuid", &host_uuid);
5371
ret = dict_get_str(dict, "source", &filename);
5373
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5374
"Unable to fetch filename from dict.");
5375
*op_errstr = gf_strdup("command unsuccessful");
5378
len = snprintf(abs_filename, sizeof(abs_filename), "%s/%s", priv->workdir,
5380
if ((len < 0) || (len >= sizeof(abs_filename))) {
5385
uuid_utoa_r(MY_UUID, uuid_str);
5386
if (!strcmp(uuid_str, host_uuid)) {
5387
ret = sys_lstat(abs_filename, &stbuf);
5389
len = snprintf(errmsg, sizeof(errmsg),
5391
"does not exist in %s",
5394
strcpy(errmsg, "<error>");
5396
*op_errstr = gf_strdup(errmsg);
5397
gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED,
5402
contents = GF_CALLOC(1, stbuf.st_size + 1, gf_common_mt_char);
5404
snprintf(errmsg, sizeof(errmsg), "Unable to allocate memory");
5405
*op_errstr = gf_strdup(errmsg);
5406
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY, "%s",
5412
fd = open(abs_filename, O_RDONLY);
5414
len = snprintf(errmsg, sizeof(errmsg), "Unable to open %s",
5417
strcpy(errmsg, "<error>");
5419
*op_errstr = gf_strdup(errmsg);
5420
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FILE_OP_FAILED, "%s",
5427
ret = sys_read(fd, buf, sizeof(buf) - 1);
5430
memcpy(contents + bytes_read, buf, ret);
5435
if (bytes_read != stbuf.st_size) {
5436
len = snprintf(errmsg, sizeof(errmsg),
5437
"Unable to read all the data from %s", abs_filename);
5439
strcpy(errmsg, "<error>");
5441
*op_errstr = gf_strdup(errmsg);
5442
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_READ_ERROR, "%s",
5448
ret = dict_set_int32(dict, "contents_size", stbuf.st_size);
5450
snprintf(errmsg, sizeof(errmsg),
5452
" contents size in dict.");
5453
*op_errstr = gf_strdup(errmsg);
5454
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "%s",
5459
ret = dict_set_int32(dict, "file_mode", (int32_t)stbuf.st_mode);
5461
snprintf(errmsg, sizeof(errmsg),
5463
" file mode in dict.");
5464
*op_errstr = gf_strdup(errmsg);
5465
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "%s",
5470
ret = dict_set_bin(dict, "common_pem_contents", contents,
5473
snprintf(errmsg, sizeof(errmsg),
5475
" pem contents in dict.");
5476
*op_errstr = gf_strdup(errmsg);
5477
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "%s",
5481
free_contents = _gf_false;
5483
free_contents = _gf_false;
5484
ret = dict_get_bin(dict, "common_pem_contents", (void **)&contents);
5486
snprintf(errmsg, sizeof(errmsg),
5488
" pem contents in dict.");
5489
*op_errstr = gf_strdup(errmsg);
5490
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
5494
ret = dict_get_int32(dict, "contents_size", &contents_size);
5496
snprintf(errmsg, sizeof(errmsg),
5498
" contents size in dict.");
5499
*op_errstr = gf_strdup(errmsg);
5500
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
5505
ret = dict_get_int32(dict, "file_mode", &file_mode);
5507
snprintf(errmsg, sizeof(errmsg),
5509
" file mode in dict.");
5510
*op_errstr = gf_strdup(errmsg);
5511
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
5516
fd = open(abs_filename, O_WRONLY | O_TRUNC | O_CREAT, 0600);
5518
len = snprintf(errmsg, sizeof(errmsg), "Unable to open %s",
5521
strcpy(errmsg, "<error>");
5523
*op_errstr = gf_strdup(errmsg);
5524
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FILE_OP_FAILED, "%s",
5530
bytes_writen = sys_write(fd, contents, contents_size);
5532
if (bytes_writen != contents_size) {
5533
len = snprintf(errmsg, sizeof(errmsg), "Failed to write to %s",
5536
strcpy(errmsg, "<error>");
5538
*op_errstr = gf_strdup(errmsg);
5539
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FILE_OP_FAILED, "%s",
5545
sys_fchmod(fd, file_mode);
5556
gf_msg_debug(this->name, 0, "Returning %d", ret);
5561
glusterd_op_gsync_set(dict_t *dict, char **op_errstr, dict_t *rsp_dict)
5565
char *host_uuid = NULL;
5566
char *secondary = NULL;
5567
char *secondary_url = NULL;
5568
char *secondary_vol = NULL;
5569
char *secondary_host = NULL;
5570
char *volname = NULL;
5571
char *path_list = NULL;
5572
glusterd_volinfo_t *volinfo = NULL;
5573
glusterd_conf_t *priv = NULL;
5574
gf_boolean_t is_force = _gf_false;
5575
char *status_msg = NULL;
5576
gf_boolean_t is_running = _gf_false;
5577
char *conf_path = NULL;
5579
xlator_t *this = THIS;
5581
priv = this->private;
5584
GF_ASSERT(op_errstr);
5585
GF_ASSERT(rsp_dict);
5587
ret = dict_get_int32(dict, "type", &type);
5591
ret = dict_get_str(dict, "host-uuid", &host_uuid);
5595
if (type == GF_GSYNC_OPTION_TYPE_STATUS) {
5596
ret = glusterd_get_gsync_status(dict, op_errstr, rsp_dict);
5600
ret = dict_get_str(dict, "secondary", &secondary);
5606
ret = dict_get_str(dict, "secondary_url", &secondary_url);
5608
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5609
"Unable to fetch secondary url.");
5613
ret = dict_get_str(dict, "secondary_host", &secondary_host);
5615
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5616
"Unable to fetch secondary hostname.");
5620
ret = dict_get_str(dict, "secondary_vol", &secondary_vol);
5622
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5623
"Unable to fetch secondary volume name.");
5627
ret = dict_get_str(dict, "conf_path", &conf_path);
5629
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5630
"Unable to fetch conf file path.");
5634
if (dict_get_str(dict, "primary", &volname) == 0) {
5635
ret = glusterd_volinfo_find(volname, &volinfo);
5637
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED,
5639
" %s (primary) not found",
5644
ret = glusterd_get_local_brickpaths(volinfo, &path_list);
5645
if (!path_list && ret == -1)
5649
if (type == GF_GSYNC_OPTION_TYPE_CONFIG) {
5650
ret = glusterd_gsync_configure(volinfo, secondary, path_list, dict,
5651
rsp_dict, op_errstr);
5653
ret = dict_set_str(rsp_dict, "conf_path", conf_path);
5655
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5656
"Unable to store conf_file_path.");
5663
if (type == GF_GSYNC_OPTION_TYPE_DELETE) {
5664
ret = glusterd_remove_secondary_in_info(volinfo, secondary, op_errstr);
5665
if (ret && !is_force && path_list)
5668
ret = glusterd_gsync_delete(volinfo, secondary, secondary_host,
5669
secondary_vol, path_list, dict, rsp_dict,
5679
is_force = dict_get_str_boolean(dict, "force", _gf_false);
5681
if (type == GF_GSYNC_OPTION_TYPE_START) {
5682
/* Add secondary to the dict indicating geo-rep session is running*/
5683
ret = dict_set_dynstr_with_alloc(volinfo->gsync_active_secondaries, key,
5686
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5687
"Unable to set key:%s"
5688
" value:running in the dict",
5693
/* If secondary volume uuid is not present in gsync_secondaries
5695
ret = glusterd_update_secondary_voluuid_secondaryinfo(volinfo);
5697
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_REMOTE_VOL_UUID_FAIL,
5699
" secondary volume uuid for old secondary info");
5703
ret = glusterd_start_gsync(volinfo, secondary, path_list, conf_path,
5704
host_uuid, op_errstr, _gf_false);
5706
/* Delete added secondary in the dict if start fails*/
5708
dict_del(volinfo->gsync_active_secondaries, key);
5711
if (type == GF_GSYNC_OPTION_TYPE_STOP ||
5712
type == GF_GSYNC_OPTION_TYPE_PAUSE ||
5713
type == GF_GSYNC_OPTION_TYPE_RESUME) {
5714
ret = glusterd_check_gsync_running_local(volinfo->volname, secondary,
5715
conf_path, &is_running);
5716
if (!ret && !is_force && path_list && (_gf_true != is_running)) {
5717
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_GSYNCD_OP_SET_FAILED,
5720
"set up for %s(primary) and %s(secondary)",
5721
volname, secondary);
5722
*op_errstr = gf_strdup(GEOREP " is not set up");
5726
if (type == GF_GSYNC_OPTION_TYPE_PAUSE) {
5727
ret = gd_pause_or_resume_gsync(dict, volname, secondary,
5728
secondary_host, secondary_vol,
5729
conf_path, op_errstr, _gf_true);
5731
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PAUSE_FAILED,
5732
GEOREP " Pause Failed");
5734
dict_del(volinfo->gsync_active_secondaries, key);
5736
} else if (type == GF_GSYNC_OPTION_TYPE_RESUME) {
5737
/* Add secondary to the dict indicating geo-rep session is
5739
ret = dict_set_dynstr_with_alloc(volinfo->gsync_active_secondaries,
5742
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5744
"key:%s value:running in dict",
5749
ret = gd_pause_or_resume_gsync(dict, volname, secondary,
5750
secondary_host, secondary_vol,
5751
conf_path, op_errstr, _gf_false);
5753
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_RESUME_FAILED,
5754
GEOREP " Resume Failed");
5755
dict_del(volinfo->gsync_active_secondaries, key);
5758
ret = stop_gsync(volname, secondary, &status_msg, conf_path,
5759
op_errstr, is_force);
5761
if (ret == 0 && status_msg)
5762
ret = dict_set_str(rsp_dict, "gsync-status", status_msg);
5764
ret = glusterd_create_status_file(volinfo->volname, secondary,
5765
secondary_host, secondary_vol,
5768
gf_msg(this->name, GF_LOG_ERROR, 0,
5769
GD_MSG_UPDATE_STATEFILE_FAILED,
5770
"Unable to update state_file. "
5774
dict_del(volinfo->gsync_active_secondaries, key);
5785
gf_msg_debug(this->name, 0, "Returning %d", ret);
5790
glusterd_get_secondary_details_confpath(glusterd_volinfo_t *volinfo,
5791
dict_t *dict, char **secondary_url,
5792
char **secondary_host,
5793
char **secondary_vol, char **conf_path,
5797
char confpath[PATH_MAX] = "";
5798
glusterd_conf_t *priv = NULL;
5799
char *secondary = NULL;
5800
xlator_t *this = THIS;
5802
priv = this->private;
5805
ret = dict_get_str(dict, "secondary", &secondary);
5806
if (ret || !secondary) {
5807
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
5808
"Unable to fetch secondary from dict");
5813
ret = glusterd_get_secondary_info(secondary, secondary_url, secondary_host,
5814
secondary_vol, op_errstr);
5816
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARYINFO_FETCH_ERROR,
5817
"Unable to fetch secondary details.");
5822
ret = dict_set_str(dict, "secondary_url", *secondary_url);
5824
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5825
"Unable to store secondary IP.");
5829
ret = dict_set_str(dict, "secondary_host", *secondary_host);
5831
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5832
"Unable to store secondary hostname");
5836
ret = dict_set_str(dict, "secondary_vol", *secondary_vol);
5838
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5839
"Unable to store secondary volume name.");
5843
ret = snprintf(confpath, sizeof(confpath) - 1,
5844
"%s/" GEOREP "/%s_%s_%s/gsyncd.conf", priv->workdir,
5845
volinfo->volname, *secondary_host, *secondary_vol);
5846
confpath[ret] = '\0';
5847
*conf_path = gf_strdup(confpath);
5848
if (!(*conf_path)) {
5849
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_STRDUP_FAILED,
5850
"Unable to gf_strdup. Error: %s", strerror(errno));
5855
ret = dict_set_str(dict, "conf_path", *conf_path);
5857
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
5858
"Unable to store conf_path");
5863
gf_msg_debug(this->name, 0, "Returning %d", ret);
5868
glusterd_get_secondary_info(char *secondary, char **secondary_url,
5869
char **hostname, char **secondary_vol,
5873
char *save_ptr = NULL;
5874
char **linearr = NULL;
5876
char errmsg[PATH_MAX] = "";
5877
xlator_t *this = THIS;
5879
ret = glusterd_urltransform_single(secondary, "normalize", &linearr);
5880
if ((ret == -1) || (linearr[0] == NULL)) {
5881
ret = snprintf(errmsg, sizeof(errmsg) - 1, "Invalid Url: %s",
5884
*op_errstr = gf_strdup(errmsg);
5885
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NORMALIZE_URL_FAIL,
5886
"Failed to normalize url");
5890
tmp = strtok_r(linearr[0], "/", &save_ptr);
5891
tmp = strtok_r(NULL, "/", &save_ptr);
5894
secondary = strtok_r(tmp, ":", &save_ptr);
5897
ret = glusterd_geo_rep_parse_secondary(secondary, hostname, op_errstr);
5899
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_URL_INVALID,
5900
"Invalid secondary url: %s", *op_errstr);
5903
gf_msg_debug(this->name, 0, "Hostname : %s", *hostname);
5905
*secondary_url = gf_strdup(secondary);
5906
if (!*secondary_url) {
5907
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STRDUP_FAILED,
5908
"Failed to gf_strdup");
5912
gf_msg_debug(this->name, 0, "Secondary URL : %s", *secondary_url);
5915
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
5916
"Invalid secondary name");
5920
secondary = strtok_r(NULL, ":", &save_ptr);
5922
*secondary_vol = gf_strdup(secondary);
5923
if (!*secondary_vol) {
5924
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STRDUP_FAILED,
5925
"Failed to gf_strdup");
5927
GF_FREE(*secondary_url);
5930
gf_msg_debug(this->name, 0, "Secondary Vol : %s", *secondary_vol);
5933
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
5934
"Invalid secondary name");
5940
glusterd_urltransform_free(linearr, 1);
5941
gf_msg_debug(this->name, 0, "Returning %d", ret);
5946
runinit_gsyncd_setrx(runner_t *runner, char *conf_path)
5949
runner_add_args(runner, GSYNCD_PREFIX "/gsyncd", "-c", NULL);
5950
runner_argprintf(runner, "%s", conf_path);
5951
runner_add_arg(runner, "--config-set-rx");
5955
glusterd_check_gsync_present(int *valid_state)
5957
char buff[PATH_MAX] = {
5967
runner_add_args(&runner, GSYNCD_PREFIX "/gsyncd", "--version", NULL);
5968
runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
5969
ret = runner_start(&runner);
5971
if (errno == ENOENT) {
5972
gf_msg("glusterd", GF_LOG_INFO, ENOENT, GD_MSG_MODULE_NOT_INSTALLED,
5975
"not installed in the system");
5978
gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_MODULE_ERROR,
5979
GEOREP " module not working as desired");
5985
ptr = fgets(buff, sizeof(buff), runner_chio(&runner, STDOUT_FILENO));
5987
if (!strstr(buff, "gsyncd")) {
5989
gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_MODULE_ERROR,
5990
GEOREP " module not working as desired");
5996
gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_MODULE_ERROR,
5997
GEOREP " module not working as desired");
6005
runner_end(&runner);
6007
gf_msg_debug("glusterd", 0, "Returning %d", ret);
6012
create_conf_file(glusterd_conf_t *conf, char *conf_path)
6013
#define RUN_GSYNCD_CMD \
6015
ret = runner_run_reuse(&runner); \
6017
runner_log(&runner, "glusterd", GF_LOG_ERROR, "command failed"); \
6018
runner_end(&runner); \
6021
runner_end(&runner); \
6028
char georepdir[PATH_MAX] = {
6031
int valid_state = 0;
6034
ret = glusterd_check_gsync_present(&valid_state);
6040
ret = snprintf(georepdir, sizeof(georepdir) - 1, "%s/" GEOREP,
6042
georepdir[ret] = '\0';
6045
* primary pre-configuration
6049
runinit_gsyncd_setrx(&runner, conf_path);
6050
runner_add_args(&runner, "remote-gsyncd", GSYNCD_PREFIX "/gsyncd", ".", ".",
6054
runinit_gsyncd_setrx(&runner, conf_path);
6055
runner_add_args(&runner, "remote-gsyncd", "/nonexistent/gsyncd", ".",
6059
/* gluster-command-dir */
6060
runinit_gsyncd_setrx(&runner, conf_path);
6061
runner_add_args(&runner, "gluster-command-dir", SBIN_DIR "/", ".", ".",
6065
/* gluster-params */
6066
runinit_gsyncd_setrx(&runner, conf_path);
6067
runner_add_args(&runner, "gluster-params", "aux-gfid-mount acl", ".", ".",
6072
runinit_gsyncd_setrx(&runner, conf_path);
6073
runner_add_arg(&runner, "ssh-command");
6074
runner_argprintf(&runner,
6075
"ssh -oPasswordAuthentication=no "
6076
"-oStrictHostKeyChecking=no "
6079
runner_add_args(&runner, ".", ".", NULL);
6082
/* ssh-command tar */
6083
runinit_gsyncd_setrx(&runner, conf_path);
6084
runner_add_arg(&runner, "ssh-command-tar");
6085
runner_argprintf(&runner,
6086
"ssh -oPasswordAuthentication=no "
6087
"-oStrictHostKeyChecking=no "
6088
"-i %s/tar_ssh.pem",
6090
runner_add_args(&runner, ".", ".", NULL);
6094
runinit_gsyncd_setrx(&runner, conf_path);
6095
runner_add_arg(&runner, "pid-file");
6097
&runner, "%s/${primaryvol}_${remotehost}_${secondaryvol}/monitor.pid",
6099
runner_add_args(&runner, ".", ".", NULL);
6102
/* geo-rep-working-dir */
6103
runinit_gsyncd_setrx(&runner, conf_path);
6104
runner_add_arg(&runner, "georep-session-working-dir");
6105
runner_argprintf(&runner, "%s/${primaryvol}_${remotehost}_${secondaryvol}/",
6107
runner_add_args(&runner, ".", ".", NULL);
6111
runinit_gsyncd_setrx(&runner, conf_path);
6112
runner_add_arg(&runner, "state-file");
6115
"%s/${primaryvol}_${remotehost}_${secondaryvol}/monitor.status",
6117
runner_add_args(&runner, ".", ".", NULL);
6120
/* state-detail-file */
6121
runinit_gsyncd_setrx(&runner, conf_path);
6122
runner_add_arg(&runner, "state-detail-file");
6123
runner_argprintf(&runner,
6124
"%s/${primaryvol}_${remotehost}_${secondaryvol}/"
6125
"${eSecondary}-detail.status",
6127
runner_add_args(&runner, ".", ".", NULL);
6131
runinit_gsyncd_setrx(&runner, conf_path);
6132
runner_add_arg(&runner, "state-socket-unencoded");
6135
"%s/${primaryvol}_${remotehost}_${secondaryvol}/${eSecondary}.socket",
6137
runner_add_args(&runner, ".", ".", NULL);
6141
runinit_gsyncd_setrx(&runner, conf_path);
6142
runner_add_args(&runner, "socketdir", GLUSTERD_SOCK_DIR, ".", ".", NULL);
6146
runinit_gsyncd_setrx(&runner, conf_path);
6147
runner_add_arg(&runner, "log-file");
6148
runner_argprintf(&runner, "%s/%s/${primaryvol}/${eSecondary}.log",
6149
conf->logdir, GEOREP);
6150
runner_add_args(&runner, ".", ".", NULL);
6153
/* changelog-log-file */
6154
runinit_gsyncd_setrx(&runner, conf_path);
6155
runner_add_arg(&runner, "changelog-log-file");
6156
runner_argprintf(&runner,
6157
"%s/%s/${primaryvol}/${eSecondary}${local_id}-changes.log",
6158
conf->logdir, GEOREP);
6159
runner_add_args(&runner, ".", ".", NULL);
6162
/* gluster-log-file */
6163
runinit_gsyncd_setrx(&runner, conf_path);
6164
runner_add_arg(&runner, "gluster-log-file");
6165
runner_argprintf(&runner,
6166
"%s/%s/${primaryvol}/${eSecondary}${local_id}.gluster.log",
6167
conf->logdir, GEOREP);
6168
runner_add_args(&runner, ".", ".", NULL);
6171
/* ignore-deletes */
6172
runinit_gsyncd_setrx(&runner, conf_path);
6173
runner_add_args(&runner, "ignore-deletes", "false", ".", ".", NULL);
6176
/* special-sync-mode */
6177
runinit_gsyncd_setrx(&runner, conf_path);
6178
runner_add_args(&runner, "special-sync-mode", "partial", ".", ".", NULL);
6181
/* change-detector == changelog */
6182
runinit_gsyncd_setrx(&runner, conf_path);
6183
runner_add_args(&runner, "change-detector", "changelog", ".", ".", NULL);
6186
runinit_gsyncd_setrx(&runner, conf_path);
6187
runner_add_arg(&runner, "working-dir");
6188
runner_argprintf(&runner, "%s/${primaryvol}/${eSecondary}",
6189
DEFAULT_GLUSTERFSD_MISC_DIRETORY);
6190
runner_add_args(&runner, ".", ".", NULL);
6194
* secondary pre-configuration
6197
/* secondary-gluster-command-dir */
6198
runinit_gsyncd_setrx(&runner, conf_path);
6199
runner_add_args(&runner, "secondary-gluster-command-dir", SBIN_DIR "/", ".",
6203
/* gluster-params */
6204
runinit_gsyncd_setrx(&runner, conf_path);
6205
runner_add_args(&runner, "gluster-params", "aux-gfid-mount acl", ".", NULL);
6209
runinit_gsyncd_setrx(&runner, conf_path);
6210
runner_add_arg(&runner, "log-file");
6213
"%s/%s-secondaries/"
6214
"${session_owner}:${local_node}${local_id}.${secondaryvol}."
6216
conf->logdir, GEOREP);
6217
runner_add_args(&runner, ".", ".", NULL);
6220
/* MountBroker log-file */
6221
runinit_gsyncd_setrx(&runner, conf_path);
6222
runner_add_arg(&runner, "log-file-mbr");
6225
"%s/%s-secondaries/mbr/"
6226
"${session_owner}:${local_node}${local_id}.${secondaryvol}."
6228
conf->logdir, GEOREP);
6229
runner_add_args(&runner, ".", ".", NULL);
6232
/* gluster-log-file */
6233
runinit_gsyncd_setrx(&runner, conf_path);
6234
runner_add_arg(&runner, "gluster-log-file");
6237
"%s/%s-secondaries/"
6238
"${session_owner}:${local_node}${local_id}.${secondaryvol}."
6240
conf->logdir, GEOREP);
6241
runner_add_args(&runner, ".", ".", NULL);
6245
return ret ? -1 : 0;
6249
glusterd_create_essential_dir_files(glusterd_volinfo_t *volinfo, dict_t *dict,
6250
char *secondary, char *secondary_host,
6251
char *secondary_vol, char **op_errstr)
6254
char *conf_path = NULL;
6255
char *statefile = NULL;
6256
char buf[PATH_MAX] = "";
6257
char errmsg[PATH_MAX] = "";
6258
glusterd_conf_t *conf = NULL;
6259
struct stat stbuf = {
6262
xlator_t *this = THIS;
6265
conf = this->private;
6267
ret = dict_get_str(dict, "conf_path", &conf_path);
6269
snprintf(errmsg, sizeof(errmsg), "Unable to fetch conf file path.");
6270
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6275
ret = dict_get_str(dict, "statefile", &statefile);
6277
snprintf(errmsg, sizeof(errmsg), "Unable to fetch statefile path.");
6278
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6283
ret = snprintf(buf, sizeof(buf), "%s/" GEOREP "/%s_%s_%s", conf->workdir,
6284
volinfo->volname, secondary_host, secondary_vol);
6285
if ((ret < 0) || (ret >= sizeof(buf))) {
6289
ret = mkdir_p(buf, 0755, _gf_true);
6291
len = snprintf(errmsg, sizeof(errmsg),
6292
"Unable to create %s"
6294
buf, strerror(errno));
6296
strcpy(errmsg, "<error>");
6298
*op_errstr = gf_strdup(errmsg);
6299
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DIR_OP_FAILED, "%s",
6304
ret = snprintf(buf, PATH_MAX, "%s/" GEOREP "/%s", conf->logdir,
6306
if ((ret < 0) || (ret >= PATH_MAX)) {
6310
ret = mkdir_p(buf, 0755, _gf_true);
6312
len = snprintf(errmsg, sizeof(errmsg),
6313
"Unable to create %s"
6315
buf, strerror(errno));
6317
strcpy(errmsg, "<error>");
6319
*op_errstr = gf_strdup(errmsg);
6320
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DIR_OP_FAILED, "%s",
6325
ret = sys_lstat(conf_path, &stbuf);
6327
gf_msg_debug(this->name, 0,
6328
"Session already running."
6329
" Not creating config file again.");
6331
ret = create_conf_file(conf, conf_path);
6332
if (ret || sys_lstat(conf_path, &stbuf)) {
6333
snprintf(errmsg, sizeof(errmsg),
6335
" config file(%s).",
6337
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_FILE_OP_FAILED, "%s",
6343
ret = sys_lstat(statefile, &stbuf);
6345
gf_msg_debug(this->name, 0,
6346
"Session already running."
6347
" Not creating status file again.");
6350
ret = glusterd_create_status_file(volinfo->volname, secondary,
6351
secondary_host, secondary_vol,
6353
if (ret || sys_lstat(statefile, &stbuf)) {
6354
snprintf(errmsg, sizeof(errmsg),
6355
"Unable to create %s"
6357
statefile, strerror(errno));
6358
*op_errstr = gf_strdup(errmsg);
6359
gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_FILE_OP_FAILED, "%s",
6367
gf_msg_debug(this->name, 0, "Returning %d", ret);
6372
glusterd_op_gsync_create(dict_t *dict, char **op_errstr, dict_t *rsp_dict)
6374
char common_pem_file[PATH_MAX] = "";
6375
char errmsg[PATH_MAX] = {
6378
char hooks_args[PATH_MAX] = "";
6379
char uuid_str[64] = "";
6380
char *host_uuid = NULL;
6381
char *secondary_url = NULL;
6382
char *secondary_url_buf = NULL;
6383
char *secondary_user = NULL;
6384
char *secondary_ip = NULL;
6385
char *save_ptr = NULL;
6386
char *secondary_host = NULL;
6387
char *secondary_vol = NULL;
6388
char *arg_buf = NULL;
6389
char *volname = NULL;
6390
char *secondary = NULL;
6392
int32_t is_pem_push = -1;
6393
int32_t ssh_port = 22;
6394
gf_boolean_t is_force = -1;
6395
glusterd_conf_t *conf = NULL;
6396
glusterd_volinfo_t *volinfo = NULL;
6397
xlator_t *this = THIS;
6398
char old_working_dir[PATH_MAX] = {0};
6399
char new_working_dir[PATH_MAX] = {0};
6400
char *secondary_voluuid = NULL;
6401
char *old_secondaryhost = NULL;
6402
gf_boolean_t is_existing_session = _gf_false;
6405
conf = this->private;
6408
GF_ASSERT(op_errstr);
6410
ret = glusterd_op_gsync_args_get(dict, op_errstr, &volname, &secondary,
6415
len = snprintf(common_pem_file, sizeof(common_pem_file),
6416
"%s" GLUSTERD_COMMON_PEM_PUB_FILE, conf->workdir);
6417
if ((len < 0) || (len >= sizeof(common_pem_file))) {
6422
ret = glusterd_volinfo_find(volname, &volinfo);
6424
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND,
6425
"Volinfo for %s (primary) not found", volname);
6429
ret = dict_get_str(dict, "secondary_vol", &secondary_vol);
6431
snprintf(errmsg, sizeof(errmsg),
6432
"Unable to fetch secondary volume name.");
6433
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6438
ret = dict_get_str(dict, "secondary_url", &secondary_url);
6440
snprintf(errmsg, sizeof(errmsg), "Unable to fetch secondary IP.");
6441
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6447
/* Fetch the secondary_user and secondary_ip from the secondary_url.
6448
* If the secondary_user is not present. Use "root"
6450
if (strstr(secondary_url, "@")) {
6451
secondary_url_buf = gf_strdup(secondary_url);
6452
if (!secondary_url_buf) {
6456
secondary_user = strtok_r(secondary_url, "@", &save_ptr);
6457
secondary_ip = strtok_r(NULL, "@", &save_ptr);
6459
secondary_user = "root";
6460
secondary_ip = secondary_url;
6463
if (!secondary_user || !secondary_ip) {
6464
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARY_URL_INVALID,
6465
"Invalid secondary url.");
6470
ret = dict_get_str(dict, "secondary_host", &secondary_host);
6472
snprintf(errmsg, sizeof(errmsg), "Unable to fetch secondary host");
6473
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6479
ret = dict_get_int32(dict, "ssh_port", &ssh_port);
6480
if (ret < 0 && ret != -ENOENT) {
6481
snprintf(errmsg, sizeof(errmsg), "Fetching ssh_port failed");
6482
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6488
is_force = dict_get_str_boolean(dict, "force", _gf_false);
6490
uuid_utoa_r(MY_UUID, uuid_str);
6491
if (!strcmp(uuid_str, host_uuid)) {
6492
ret = dict_get_int32(dict, "push_pem", &is_pem_push);
6493
if (!ret && is_pem_push) {
6494
gf_msg_debug(this->name, 0,
6496
" pem files in secondary");
6501
len = snprintf(hooks_args, sizeof(hooks_args),
6502
"is_push_pem=%d,pub_file=%s,secondary_user=%s,"
6503
"secondary_ip=%s,secondary_vol=%s,ssh_port=%d",
6504
is_pem_push, common_pem_file, secondary_user,
6505
secondary_ip, secondary_vol, ssh_port);
6506
if ((len < 0) || (len >= sizeof(hooks_args))) {
6511
snprintf(hooks_args, sizeof(hooks_args),
6512
"This argument will stop the hooks script");
6514
arg_buf = gf_strdup(hooks_args);
6516
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_STRDUP_FAILED,
6517
"Failed to gf_strdup");
6520
goto create_essentials;
6526
ret = dict_set_str(dict, "hooks_args", arg_buf);
6528
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
6529
"Failed to set hooks_args in dict.");
6532
goto create_essentials;
6538
/* Fetch secondary volume uuid, to get stored in volume info. */
6539
ret = dict_get_str(dict, "secondary_voluuid", &secondary_voluuid);
6541
snprintf(errmsg, sizeof(errmsg),
6542
"Unable to fetch secondary volume uuid from dict");
6543
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6549
is_existing_session = dict_get_str_boolean(dict, "existing_session",
6551
if (is_existing_session) {
6552
ret = dict_get_str(dict, "old_secondaryhost", &old_secondaryhost);
6554
snprintf(errmsg, sizeof(errmsg),
6555
"Unable to fetch old_secondaryhost");
6556
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, "%s",
6562
/* Rename existing geo-rep session with new Secondary Host */
6563
ret = snprintf(old_working_dir, sizeof(old_working_dir) - 1,
6564
"%s/" GEOREP "/%s_%s_%s", conf->workdir,
6565
volinfo->volname, old_secondaryhost, secondary_vol);
6567
ret = snprintf(new_working_dir, sizeof(new_working_dir) - 1,
6568
"%s/" GEOREP "/%s_%s_%s", conf->workdir,
6569
volinfo->volname, secondary_host, secondary_vol);
6571
ret = sys_rename(old_working_dir, new_working_dir);
6573
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_FORCE_CREATE_SESSION,
6574
"rename of old working dir %s to "
6575
"new working dir %s is done! ",
6576
old_working_dir, new_working_dir);
6578
if (errno == ENOENT) {
6579
/* log error, but proceed with directory
6581
gf_msg_debug(this->name, 0,
6582
"old_working_dir(%s) "
6586
len = snprintf(errmsg, sizeof(errmsg),
6587
"rename of old working dir %s "
6588
"to new working dir %s "
6589
"failed! Error: %s",
6590
old_working_dir, new_working_dir,
6593
strcpy(errmsg, "<error>");
6595
gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_FORCE_CREATE_SESSION,
6596
"rename of old working dir %s to "
6597
"new working dir %s failed! Error: %s!",
6598
old_working_dir, new_working_dir, strerror(errno));
6606
ret = glusterd_create_essential_dir_files(
6607
volinfo, dict, secondary, secondary_host, secondary_vol, op_errstr);
6611
ret = glusterd_store_secondary_in_info(
6612
volinfo, secondary, host_uuid, secondary_voluuid, op_errstr, is_force);
6614
snprintf(errmsg, sizeof(errmsg),
6616
" secondary info.");
6617
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SECONDARYINFO_STORE_ERROR,
6622
/* Enable marker and changelog */
6623
ret = glusterd_set_gsync_confs(volinfo);
6625
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_MARKER_START_FAIL,
6628
snprintf(errmsg, sizeof(errmsg), "Index initialization failed");
6635
if (ret && errmsg[0] != '\0') {
6636
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_GSYNCD_ERROR, "%s", errmsg);
6637
*op_errstr = gf_strdup(errmsg);
6640
GF_FREE(secondary_url_buf);
6641
gf_msg_debug(this->name, 0, "Returning %d", ret);