3604df
From 35836d9ffe89e5891c91baeb3812974baa221441 Mon Sep 17 00:00:00 2001
3604df
From: Avra Sengupta <asengupt@redhat.com>
3604df
Date: Mon, 19 Dec 2016 13:52:59 +0530
3604df
Subject: [PATCH 247/257] snapshot: Fix restore rollback to reassign snap
3604df
 volume ids to bricks
3604df
3604df
Added further checks to ensure we do not go beyond prevalidate
3604df
when trying to restore a snapshot which has a nfs-gansha conf
3604df
file, in a cluster when nfs-ganesha is not enabled
3604df
3604df
The error message for the particular scenario is:
3604df
"Snapshot(<snapname>) has a nfs-ganesha export conf
3604df
file. cluster.enable-shared-storage and nfs-ganesha
3604df
should be enabled before restoring this snapshot."
3604df
3604df
> Reviewed-on: http://review.gluster.org/16116
3604df
> Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
3604df
> Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
3604df
Change-Id: I1b87e9907e0a5e162f26ef1ca89fe76e8da8610f
3604df
BUG: 1403672
3604df
Signed-off-by: Avra Sengupta <asengupt@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/93275
3604df
Reviewed-by: Jiffin Thottan <jthottan@redhat.com>
3604df
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
3604df
---
3604df
 xlators/mgmt/glusterd/src/glusterd-errno.h         |   1 +
3604df
 xlators/mgmt/glusterd/src/glusterd-ganesha.c       |  32 ++++++
3604df
 xlators/mgmt/glusterd/src/glusterd-messages.h      |  19 +++-
3604df
 .../mgmt/glusterd/src/glusterd-snapshot-utils.c    |   1 +
3604df
 xlators/mgmt/glusterd/src/glusterd-snapshot.c      | 112 +++++++++++++++++++++
3604df
 xlators/mgmt/glusterd/src/glusterd.h               |   3 +
3604df
 6 files changed, 163 insertions(+), 5 deletions(-)
3604df
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-errno.h b/xlators/mgmt/glusterd/src/glusterd-errno.h
3604df
index 55d44a5..3301e44 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-errno.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-errno.h
3604df
@@ -27,6 +27,7 @@ enum glusterd_op_errno {
3604df
         EG_ISSNAP      = 30813,          /* Volume is a snap volume           */
3604df
         EG_GEOREPRUN   = 30814,          /* Geo-Replication is running        */
3604df
         EG_NOTTHINP    = 30815,          /* Bricks are not thinly provisioned */
3604df
+        EG_NOGANESHA   = 30816,          /* Global nfs-ganesha is not enabled */
3604df
 };
3604df
 
3604df
 #endif
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-ganesha.c b/xlators/mgmt/glusterd/src/glusterd-ganesha.c
3604df
index 470d455..93c35c7 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-ganesha.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-ganesha.c
3604df
@@ -160,6 +160,38 @@ manage_service (char *action)
3604df
                 " not recognized.", action);
3604df
         return ret;
3604df
 }
3604df
+
3604df
+/*
3604df
+ * Check if the cluster is a ganesha cluster or not *
3604df
+ */
3604df
+gf_boolean_t
3604df
+glusterd_is_ganesha_cluster () {
3604df
+        int                ret      = -1;
3604df
+        glusterd_conf_t   *priv     = NULL;
3604df
+        xlator_t          *this     = NULL;
3604df
+        gf_boolean_t       ret_bool = _gf_false;
3604df
+
3604df
+        this = THIS;
3604df
+        GF_VALIDATE_OR_GOTO ("ganesha", this, out);
3604df
+        priv = this->private;
3604df
+        GF_VALIDATE_OR_GOTO (this->name, priv, out);
3604df
+
3604df
+        ret = dict_get_str_boolean (priv->opts,
3604df
+                                    GLUSTERD_STORE_KEY_GANESHA_GLOBAL,
3604df
+                                    _gf_false);
3604df
+        if (ret == _gf_true) {
3604df
+                ret_bool = _gf_true;
3604df
+                gf_msg_debug (this->name, 0,
3604df
+                              "nfs-ganesha is enabled for the cluster");
3604df
+        } else
3604df
+                gf_msg_debug (this->name, 0,
3604df
+                              "nfs-ganesha is disabled for the cluster");
3604df
+
3604df
+out:
3604df
+        return ret_bool;
3604df
+
3604df
+}
3604df
+
3604df
 /* Check if ganesha.enable is set to 'on', that checks if
3604df
  * a  particular volume is exported via NFS-Ganesha */
3604df
 gf_boolean_t
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-messages.h b/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
index e39fb92..126a583 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
@@ -41,7 +41,7 @@
3604df
 
3604df
 #define GLUSTERD_COMP_BASE      GLFS_MSGID_GLUSTERD
3604df
 
3604df
-#define GLFS_NUM_MESSAGES       587
3604df
+#define GLFS_NUM_MESSAGES       589
3604df
 
3604df
 #define GLFS_MSGID_END          (GLUSTERD_COMP_BASE + GLFS_NUM_MESSAGES + 1)
3604df
 /* Messaged with message IDs */
3604df
@@ -4728,7 +4728,7 @@
3604df
  * @recommendation
3604df
  *
3604df
  */
3604df
-#define GD_MSG_BRICK_CLEANUP_SUCCESS               (GLUSTERD_COMP_BASE + 584)
3604df
+#define GD_MSG_BRICK_CLEANUP_SUCCESS               (GLUSTERD_COMP_BASE + 585)
3604df
 
3604df
 /*!
3604df
  * @messageid
3604df
@@ -4736,7 +4736,7 @@
3604df
  * @recommendation
3604df
  *
3604df
  */
3604df
-#define GD_MSG_STATE_STR_GET_FAILED               (GLUSTERD_COMP_BASE + 585)
3604df
+#define GD_MSG_STATE_STR_GET_FAILED               (GLUSTERD_COMP_BASE + 586)
3604df
 
3604df
 /*!
3604df
  * @messageid
3604df
@@ -4744,7 +4744,7 @@
3604df
  * @recommendedaction
3604df
  *
3604df
  */
3604df
-#define GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD   (GLUSTERD_COMP_BASE + 586)
3604df
+#define GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD   (GLUSTERD_COMP_BASE + 587)
3604df
 
3604df
 /*!
3604df
  * @messageid
3604df
@@ -4752,7 +4752,16 @@
3604df
  * @recommendedaction
3604df
  *
3604df
  */
3604df
-#define GD_MSG_RESET_BRICK_CMD_FAIL                (GLUSTERD_COMP_BASE + 587)
3604df
+#define GD_MSG_RESET_BRICK_CMD_FAIL                (GLUSTERD_COMP_BASE + 588)
3604df
+
3604df
+/*!
3604df
+ * @messageid
3604df
+ * @diagnosis
3604df
+ * @recommendedaction
3604df
+ *
3604df
+ */
3604df
+#define GD_MSG_NFS_GANESHA_DISABLED                (GLUSTERD_COMP_BASE + 589)
3604df
+
3604df
 /*------------*/
3604df
 #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
3604df
 #endif /* !_GLUSTERD_MESSAGES_H_ */
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
index 4a3a2f7..26b2f73 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
@@ -3787,6 +3787,7 @@ glusterd_copy_nfs_ganesha_file (glusterd_volinfo_t *src_vol,
3604df
                                 GD_MSG_FILE_OP_FAILED,
3604df
                                 "Failed to open %s",
3604df
                                 dest ? src_path : dest_path);
3604df
+                        ret = -1;
3604df
                         goto out;
3604df
                 }
3604df
 
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
3604df
index 70595ef..47835a8 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
3604df
@@ -919,6 +919,76 @@ out:
3604df
         return ret;
3604df
 }
3604df
 
3604df
+/*
3604df
+ * This function validates the particulat snapshot with respect to the current
3604df
+ * cluster. If the snapshot has ganesha enabled, and the cluster is not a nfs
3604df
+ * ganesha cluster, we fail the validation. Other scenarios where either the
3604df
+ * snapshot does not have ganesha enabled or it has and the cluster is a nfs
3604df
+ * ganesha cluster, we pass the validation
3604df
+ *
3604df
+ * @param snap          snap object of the snapshot to be validated
3604df
+ * @return              Negative value on Failure and 0 in success
3604df
+ */
3604df
+int32_t
3604df
+glusterd_snapshot_validate_ganesha_conf (glusterd_snap_t *snap,
3604df
+                                         char **op_errstr,
3604df
+                                         uint32_t *op_errno)
3604df
+{
3604df
+        int                     ret                    = -1;
3604df
+        glusterd_volinfo_t      *snap_vol              = NULL;
3604df
+        xlator_t                *this                  = NULL;
3604df
+
3604df
+        this = THIS;
3604df
+        GF_VALIDATE_OR_GOTO ("snapshot", this, out);
3604df
+        GF_VALIDATE_OR_GOTO (this->name, snap, out);
3604df
+        GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
3604df
+        GF_VALIDATE_OR_GOTO (this->name, op_errno, out);
3604df
+
3604df
+        snap_vol = list_entry (snap->volumes.next,
3604df
+                               glusterd_volinfo_t, vol_list);
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (this->name, snap_vol, out);
3604df
+
3604df
+        /*
3604df
+         * Check if the snapshot has ganesha enabled *
3604df
+         */
3604df
+        if (glusterd_check_ganesha_export(snap_vol) == _gf_false) {
3604df
+                /*
3604df
+                 * If the snapshot has not been exported via ganesha *
3604df
+                 * then we can proceed.                              *
3604df
+                 */
3604df
+                ret = 0;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        /*
3604df
+         * At this point we are certain that the snapshot has been exported *
3604df
+         * via ganesha. So we check if the cluster is a nfs-ganesha cluster *
3604df
+         * If it a nfs-ganesha cluster, then we proceed. Else we fail.      *
3604df
+         */
3604df
+        if (glusterd_is_ganesha_cluster() != _gf_true) {
3604df
+                ret = gf_asprintf (op_errstr, "Snapshot(%s) has a "
3604df
+                                   "nfs-ganesha export conf file. "
3604df
+                                   "cluster.enable-shared-storage and "
3604df
+                                   "nfs-ganesha should be enabled "
3604df
+                                   "before restoring this snapshot.",
3604df
+                                   snap->snapname);
3604df
+                *op_errno = EG_NOGANESHA;
3604df
+                if (ret < 0) {
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                gf_msg (this->name, GF_LOG_ERROR, EINVAL,
3604df
+                        GD_MSG_NFS_GANESHA_DISABLED, "%s", *op_errstr);
3604df
+                ret = -1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
 /* This function is called before actual restore is taken place. This function
3604df
  * will validate whether the snapshot volumes are ready to be restored or not.
3604df
  *
3604df
@@ -989,6 +1059,15 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr,
3604df
                 goto out;
3604df
         }
3604df
 
3604df
+        ret = glusterd_snapshot_validate_ganesha_conf (snap, op_errstr,
3604df
+                                                       op_errno);
3604df
+        if (ret) {
3604df
+                gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                        GD_MSG_SNAPSHOT_OP_FAILED,
3604df
+                        "ganesha conf validation failed.");
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
         ret = dict_set_str (rsp_dict, "snapname", snapname);
3604df
         if (ret) {
3604df
                 gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
@@ -8844,6 +8923,7 @@ glusterd_snapshot_revert_partial_restored_vol (glusterd_volinfo_t *volinfo)
3604df
         int                     ret                     = 0;
3604df
         char                    pathname [PATH_MAX]     = {0,};
3604df
         char                    trash_path[PATH_MAX]    = {0,};
3604df
+        glusterd_brickinfo_t   *brickinfo               = NULL;
3604df
         glusterd_volinfo_t     *reverted_vol            = NULL;
3604df
         glusterd_volinfo_t     *snap_vol                = NULL;
3604df
         glusterd_volinfo_t     *tmp_vol                 = NULL;
3604df
@@ -8898,6 +8978,38 @@ glusterd_snapshot_revert_partial_restored_vol (glusterd_volinfo_t *volinfo)
3604df
                                       snapvol_list) {
3604df
                 cds_list_add_tail (&snap_vol->snapvol_list,
3604df
                                    &reverted_vol->snap_volumes);
3604df
+
3604df
+                cds_list_for_each_entry (brickinfo, &snap_vol->bricks,
3604df
+                                         brick_list) {
3604df
+                        /*
3604df
+                         * If the brick is not of this peer, or snapshot is    *
3604df
+                         * missed for the brick don't restore the xattr for it *
3604df
+                         */
3604df
+                        if ((!gf_uuid_compare (brickinfo->uuid, MY_UUID)) &&
3604df
+                            (brickinfo->snap_status != -1)) {
3604df
+                                /*
3604df
+                                 * We need to restore volume id of all snap *
3604df
+                                 * bricks to volume id of the snap volume.  *
3604df
+                                 */
3604df
+                                ret = sys_lsetxattr (brickinfo->path,
3604df
+                                                     GF_XATTR_VOL_ID_KEY,
3604df
+                                                     snap_vol->volume_id,
3604df
+                                                   sizeof (snap_vol->volume_id),
3604df
+                                                     XATTR_REPLACE);
3604df
+                                if (ret == -1) {
3604df
+                                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                                GD_MSG_SETXATTR_FAIL,
3604df
+                                                "Failed to set extended "
3604df
+                                                "attribute %s on %s. "
3604df
+                                                "Reason: %s, snap: %s",
3604df
+                                                GF_XATTR_VOL_ID_KEY,
3604df
+                                                brickinfo->path,
3604df
+                                                strerror (errno),
3604df
+                                                snap_vol->volname);
3604df
+                                        goto out;
3604df
+                                }
3604df
+                        }
3604df
+                }
3604df
         }
3604df
 
3604df
         /* Since we retrieved the volinfo from store now we don't
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
3604df
index b926383..a21b0a1 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd.h
3604df
@@ -1077,6 +1077,9 @@ int glusterd_op_stage_set_ganesha (dict_t *dict, char **op_errstr);
3604df
 int glusterd_op_set_ganesha (dict_t *dict, char **errstr);
3604df
 int ganesha_manage_export (dict_t *dict, char *value, char **op_errstr);
3604df
 int manage_export_config (char *volname, char *value, char **op_errstr);
3604df
+
3604df
+gf_boolean_t
3604df
+glusterd_is_ganesha_cluster ();
3604df
 gf_boolean_t glusterd_check_ganesha_export (glusterd_volinfo_t *volinfo);
3604df
 int stop_ganesha (char **op_errstr);
3604df
 int tear_down_cluster (gf_boolean_t run_teardown);
3604df
-- 
3604df
2.9.3
3604df