glusterfs

Форк
0
/
glusterd-reset-brick.c 
367 строк · 11.9 Кб
1
/*
2
   Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
3
   This file is part of GlusterFS.
4

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.
9
*/
10
#include <glusterfs/common-utils.h>
11
#include <glusterfs/glusterfs.h>
12
#include "glusterd-op-sm.h"
13
#include "glusterd-geo-rep.h"
14
#include "glusterd-store.h"
15
#include "glusterd-utils.h"
16
#include "glusterd-svc-mgmt.h"
17
#include "glusterd-svc-helper.h"
18
#include "glusterd-volgen.h"
19
#include "glusterd-messages.h"
20
#include "glusterd-mgmt.h"
21
#include <glusterfs/run.h>
22
#include <glusterfs/syscall.h>
23

24
#include <signal.h>
25

26
int
27
glusterd_reset_brick_prevalidate(dict_t *dict, char **op_errstr,
28
                                 dict_t *rsp_dict)
29
{
30
    int ret = 0;
31
    char *src_brick = NULL;
32
    char *dst_brick = NULL;
33
    char *volname = NULL;
34
    char *op = NULL;
35
    glusterd_op_t gd_op = -1;
36
    glusterd_volinfo_t *volinfo = NULL;
37
    glusterd_brickinfo_t *src_brickinfo = NULL;
38
    char *host = NULL;
39
    char msg[2048] = {0};
40
    glusterd_peerinfo_t *peerinfo = NULL;
41
    glusterd_brickinfo_t *dst_brickinfo = NULL;
42
    glusterd_conf_t *priv = NULL;
43
    char pidfile[PATH_MAX] = {0};
44
    xlator_t *this = THIS;
45
    gf_boolean_t is_force = _gf_false;
46
    int32_t ignore_partition = 0;
47
    pid_t pid = -1;
48
    uuid_t volume_id = {
49
        0,
50
    };
51
    char *dup_dstbrick = NULL;
52

53
    priv = this->private;
54
    GF_ASSERT(priv);
55

56
    ret = glusterd_brick_op_prerequisites(dict, &op, &gd_op, &volname, &volinfo,
57
                                          &src_brick, &src_brickinfo, pidfile,
58
                                          op_errstr, rsp_dict);
59
    if (ret)
60
        goto out;
61

62
    if (!strcmp(op, "GF_RESET_OP_START"))
63
        goto done;
64

65
    if (!strcmp(op, "GF_RESET_OP_COMMIT_FORCE"))
66
        is_force = _gf_true;
67

68
    ret = glusterd_get_dst_brick_info(&dst_brick, volname, op_errstr,
69
                                      &dst_brickinfo, &host, dict,
70
                                      &dup_dstbrick);
71
    if (ret)
72
        goto out;
73

74
    ret = glusterd_new_brick_validate(dst_brick, dst_brickinfo, msg,
75
                                      sizeof(msg), op);
76
    /* if bricks are not same and reset brick was used, fail command.
77
     * Only replace brick should be used to replace with new bricks
78
     * to the volume.
79
     */
80
    if (ret == 0) {
81
        if (!gf_uuid_compare(MY_UUID, dst_brickinfo->uuid)) {
82
            ret = -1;
83
            *op_errstr = gf_strdup(
84
                "When destination brick is new,"
85
                " please use"
86
                " gluster volume "
87
                "replace-brick <volname> "
88
                "<src-brick> <dst-brick> "
89
                "commit force");
90
            if (*op_errstr)
91
                gf_msg(this->name, GF_LOG_ERROR, EPERM,
92
                       GD_MSG_BRICK_VALIDATE_FAIL, "%s", *op_errstr);
93
            goto out;
94
        }
95
    } else if (ret == 1) {
96
        if (gf_is_service_running(pidfile, &pid)) {
97
            ret = -1;
98
            *op_errstr = gf_strdup(
99
                "Source brick"
100
                " must be stopped."
101
                " Please use "
102
                "gluster volume "
103
                "reset-brick <volname> "
104
                "<dst-brick> start.");
105
            if (*op_errstr)
106
                gf_msg(this->name, GF_LOG_ERROR, EPERM,
107
                       GD_MSG_BRICK_VALIDATE_FAIL, "%s", *op_errstr);
108
            goto out;
109
        }
110
        ret = sys_lgetxattr(dst_brickinfo->path, GF_XATTR_VOL_ID_KEY, volume_id,
111
                            16);
112
        if (gf_uuid_compare(dst_brickinfo->uuid, src_brickinfo->uuid) ||
113
            (ret >= 0 && is_force == _gf_false)) {
114
            ret = -1;
115
            *op_errstr = gf_strdup(
116
                "Brick not available."
117
                "It may be containing "
118
                "or be contained "
119
                "by an existing brick."
120
                "Use 'force' option to "
121
                "override this.");
122
            if (*op_errstr)
123
                gf_msg(this->name, GF_LOG_ERROR, EPERM,
124
                       GD_MSG_BRICK_VALIDATE_FAIL, "%s", *op_errstr);
125
            goto out;
126
        }
127
        ret = 0;
128
    } else {
129
        *op_errstr = gf_strdup(msg);
130
        ret = -1;
131
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_VALIDATE_FAIL, "%s",
132
               *op_errstr);
133
        goto out;
134
    }
135

136
    volinfo->rep_brick.src_brick = src_brickinfo;
137
    volinfo->rep_brick.dst_brick = dst_brickinfo;
138

139
    ret = dict_get_int32(dict, "ignore-partition", &ignore_partition);
140
    ret = 0;
141
    if (glusterd_gf_is_local_addr(host)) {
142
        ret = glusterd_validate_and_create_brickpath(
143
            dst_brickinfo, volinfo->volume_id, volinfo->volname, op_errstr,
144
            is_force, ignore_partition);
145
        if (ret)
146
            goto out;
147
    } else {
148
        RCU_READ_LOCK;
149

150
        peerinfo = glusterd_peerinfo_find(NULL, host);
151
        if (peerinfo == NULL) {
152
            RCU_READ_UNLOCK;
153
            ret = -1;
154
            snprintf(msg, sizeof(msg), "%s, is not a friend.", host);
155
            *op_errstr = gf_strdup(msg);
156
            goto out;
157

158
        } else if (!peerinfo->connected) {
159
            RCU_READ_UNLOCK;
160
            ret = -1;
161
            snprintf(msg, sizeof(msg),
162
                     "%s,"
163
                     "is not connected at "
164
                     "the moment.",
165
                     host);
166
            *op_errstr = gf_strdup(msg);
167
            goto out;
168

169
        } else if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state) {
170
            RCU_READ_UNLOCK;
171
            ret = -1;
172
            snprintf(msg, sizeof(msg),
173
                     "%s, is not befriended "
174
                     "at the moment.",
175
                     host);
176
            *op_errstr = gf_strdup(msg);
177
            goto out;
178
        }
179
        RCU_READ_UNLOCK;
180
    }
181

182
    if (!(gf_uuid_compare(dst_brickinfo->uuid, MY_UUID))) {
183
        ret = glusterd_get_brick_mount_dir(dst_brickinfo->path,
184
                                           dst_brickinfo->hostname,
185
                                           dst_brickinfo->mount_dir);
186
        if (ret) {
187
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_MOUNTDIR_GET_FAIL,
188
                   "Failed to get brick mount_dir");
189
            goto out;
190
        }
191
        ret = dict_set_dynstr_with_alloc(rsp_dict, "brick1.mount_dir",
192
                                         dst_brickinfo->mount_dir);
193
        if (ret) {
194
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
195
                   "Failed to set brick.mount_dir");
196
            goto out;
197
        }
198
    }
199

200
    ret = dict_set_int32_sizen(rsp_dict, "brick_count", 1);
201
    if (ret) {
202
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
203
               "Failed to set local_brick_count.");
204
        goto out;
205
    }
206

207
done:
208
    ret = 0;
209
out:
210
    GF_FREE(dup_dstbrick);
211
    gf_msg_debug(this->name, 0, "Returning %d.", ret);
212

213
    return ret;
214
}
215

216
int
217
glusterd_op_reset_brick(dict_t *dict, dict_t *rsp_dict)
218
{
219
    int ret = 0;
220
    char *op = NULL;
221
    glusterd_volinfo_t *volinfo = NULL;
222
    char *volname = NULL;
223
    xlator_t *this = THIS;
224
    glusterd_conf_t *priv = NULL;
225
    char *src_brick = NULL;
226
    char *dst_brick = NULL;
227
    glusterd_brickinfo_t *src_brickinfo = NULL;
228
    glusterd_brickinfo_t *dst_brickinfo = NULL;
229

230
    priv = this->private;
231
    GF_ASSERT(priv);
232

233
    ret = dict_get_str(dict, "operation", &op);
234
    if (ret) {
235
        gf_msg_debug(this->name, 0, "dict_get on operation failed");
236
        goto out;
237
    }
238

239
    ret = dict_get_str(dict, "volname", &volname);
240
    if (ret) {
241
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
242
               "Unable to get volume name");
243
        goto out;
244
    }
245

246
    ret = glusterd_volinfo_find(volname, &volinfo);
247
    if (ret)
248
        goto out;
249

250
    ret = dict_get_str(dict, "src-brick", &src_brick);
251
    if (ret) {
252
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
253
               "Unable to get src brick");
254
        goto out;
255
    }
256

257
    gf_msg_debug(this->name, 0, "src brick=%s", src_brick);
258

259
    ret = glusterd_volume_brickinfo_get_by_brick(src_brick, volinfo,
260
                                                 &src_brickinfo, _gf_false);
261
    if (ret) {
262
        gf_msg_debug(this->name, 0, "Unable to get src-brickinfo");
263
        goto out;
264
    }
265

266
    if (!strcmp(op, "GF_RESET_OP_START")) {
267
        ret = glusterd_volume_stop_glusterfs(volinfo, src_brickinfo, _gf_false);
268
        if (ret) {
269
            gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_BRICK_STOP_FAIL,
270
                   "Unable to stop"
271
                   " brick: %s:%s",
272
                   src_brickinfo->hostname, src_brickinfo->path);
273
        }
274

275
        goto out;
276

277
    } else if (!strcmp(op, "GF_RESET_OP_COMMIT") ||
278
               !strcmp(op, "GF_RESET_OP_COMMIT_FORCE")) {
279
        ret = dict_get_str(dict, "dst-brick", &dst_brick);
280
        if (ret) {
281
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
282
                   "Unable to get dst brick");
283
            goto out;
284
        }
285

286
        gf_msg_debug(this->name, 0, "dst brick=%s", dst_brick);
287

288
        ret = glusterd_get_rb_dst_brickinfo(volinfo, &dst_brickinfo);
289
        if (ret) {
290
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_RB_BRICKINFO_GET_FAIL,
291
                   "Unable to get "
292
                   "reset brick "
293
                   "destination brickinfo");
294
            goto out;
295
        }
296

297
        ret = glusterd_resolve_brick(dst_brickinfo);
298
        if (ret) {
299
            gf_msg_debug(this->name, 0, "Unable to resolve dst-brickinfo");
300
            goto out;
301
        }
302

303
        ret = rb_update_dstbrick_port(dst_brickinfo, rsp_dict, dict);
304
        if (ret)
305
            goto out;
306

307
        if (gf_uuid_compare(dst_brickinfo->uuid, MY_UUID)) {
308
            gf_msg_debug(this->name, 0, "I AM THE DESTINATION HOST");
309
            ret = glusterd_volume_stop_glusterfs(volinfo, src_brickinfo,
310
                                                 _gf_false);
311
            if (ret) {
312
                gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_BRICK_STOP_FAIL,
313
                       "Unable to stop brick: %s:%s", src_brickinfo->hostname,
314
                       src_brickinfo->path);
315
                goto out;
316
            }
317
        }
318

319
        ret = glusterd_svcs_stop(volinfo);
320
        if (ret) {
321
            gf_msg(this->name, GF_LOG_ERROR, 0,
322
                   GD_MSG_GLUSTER_SERVICES_STOP_FAIL,
323
                   "Unable to stop gluster services, ret: %d", ret);
324
            goto out;
325
        }
326
        ret = glusterd_op_perform_replace_brick(volinfo, src_brick, dst_brick,
327
                                                dict);
328
        if (ret) {
329
            gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_BRICK_ADD_FAIL,
330
                   "Unable to add dst-brick: "
331
                   "%s to volume: %s",
332
                   dst_brick, volinfo->volname);
333
            (void)glusterd_svcs_manager(volinfo);
334
            goto out;
335
        }
336

337
        if (volinfo->rebal.defrag_status != GF_DEFRAG_STATUS_NOT_STARTED)
338
            volinfo->rebal.defrag_status = GF_DEFRAG_STATUS_RESET_DUE_RESET_BRC;
339

340
        ret = glusterd_svcs_manager(volinfo);
341
        if (ret) {
342
            gf_msg(this->name, GF_LOG_CRITICAL, 0,
343
                   GD_MSG_GLUSTER_SERVICE_START_FAIL,
344
                   "Failed to start one or more gluster services.");
345
        }
346

347
        ret = glusterd_fetchspec_notify(THIS);
348
        glusterd_brickinfo_delete(volinfo->rep_brick.dst_brick);
349
        volinfo->rep_brick.src_brick = NULL;
350
        volinfo->rep_brick.dst_brick = NULL;
351

352
        if (!ret)
353
            ret = glusterd_store_volinfo(volinfo,
354
                                         GLUSTERD_VOLINFO_VER_AC_INCREMENT);
355
        if (ret) {
356
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_RBOP_STATE_STORE_FAIL,
357
                   "Couldn't store"
358
                   " reset brick operation's state.");
359
        }
360
    } else {
361
        ret = -1;
362
        goto out;
363
    }
364

365
out:
366
    return ret;
367
}
368

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.