summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
Diffstat (limited to 'xlators')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c814
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c186
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h9
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c33
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.h4
5 files changed, 987 insertions, 59 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
index b5859faaf..3e98e2fa2 100644
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
@@ -955,65 +955,6 @@ out:
return ret;
}
-int
-glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr,
- dict_t *rsp_dict)
-{
- int snap_command = 0;
- xlator_t *this = NULL;
- int ret = -1;
-
- this = THIS;
-
- GF_ASSERT (this);
- GF_ASSERT (dict);
- GF_ASSERT (rsp_dict); //not sure if this is needed, verify.
-
- ret = dict_get_int32 (dict, "type", &snap_command);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "unable to get the type of "
- "the snapshot command");
- goto out;
- }
-
- switch (snap_command) {
- case (GF_SNAP_OPTION_TYPE_CREATE):
- ret = glusterd_snapshot_create_prevalidate (dict, op_errstr,
- rsp_dict);
- if (ret) {
- gf_log (this->name, GF_LOG_WARNING, "Snapshot create "
- "pre-validation failed");
- goto out;
- }
- break;
-
- case (GF_SNAP_OPTION_TYPE_CONFIG):
- ret = glusterd_snapshot_config_prevalidate (dict, op_errstr);
- if (ret) {
- gf_log (this->name, GF_LOG_WARNING, "Snapshot config "
- "pre-validation failed");
- goto out;
- }
- break;
-
- case GF_SNAP_OPTION_TYPE_RESTORE:
- ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr);
- if (ret) {
- gf_log (this->name, GF_LOG_WARNING, "Snapshot restore "
- "validation failed");
- goto out;
- }
- break;
- default:
- gf_log (this->name, GF_LOG_WARNING, "invalid snap command");
- goto out;
- }
-
- ret = 0;
-out:
- return ret;
-}
-
glusterd_snap_t*
glusterd_new_snap_object()
{
@@ -2665,6 +2606,55 @@ out:
return ret;
}
+int32_t
+glusterd_snap_delete (glusterd_snap_t *snap)
+{
+ int32_t ret = -1;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!snap) {
+ gf_log (this->name, GF_LOG_WARNING, "snap object is NULL");
+ goto out;
+ }
+
+ GF_FREE (snap->description);
+ ret = glusterd_volinfo_delete (snap->snap_volume);
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING, "deleting the snap volume"
+ "failed for the snap %s", snap->snap_name);
+ GF_FREE (snap);
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int32_t
+glusterd_cg_delete (glusterd_snap_cg_t *cg)
+{
+ int32_t ret = -1;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!cg) {
+ gf_log (this->name, GF_LOG_WARNING, "consistency group is "
+ "NULL");
+ goto out;
+ }
+
+ GF_FREE (cg->description);
+ GF_FREE (cg);
+ ret = 0;
+
+out:
+ return ret;
+}
+
/* this should be the last thing to be done.
1. Do op stage related checks such as whether volume is there or not etc
2. Do quorum checks.
@@ -3260,6 +3250,626 @@ out:
return snapname;
}
+/* This is a snapshot remove handler function. This function will be
+ * executed in the originator node. This function is responsible for
+ * calling mgmt v3 framework to do the actual remove on all the bricks
+ *
+ * @param req RPC request object
+ * @param op gluster operation
+ * @param dict dictionary containing snapshot remove request
+ * @param err_str In case of an err this string should be populated
+ * @param len length of err_str buffer
+ *
+ * @return Negative value on Failure and 0 in success
+ */
+int
+glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op,
+ dict_t *dict, char *err_str, size_t len)
+{
+ int ret = -1;
+ int64_t vol_count = 0;
+ char *volname = NULL;
+ char *snapname = NULL;
+ char *cgname = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_snap_cg_t *cg = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+
+ GF_ASSERT (conf);
+ GF_ASSERT (req);
+ GF_ASSERT (dict);
+ GF_ASSERT (err_str);
+
+ /* If volume name is provided then volcount will be set */
+ ret = dict_get_int64 (dict, "volcount", &vol_count);
+ if (ret) {
+ /* If volcount is not provided then cgname must be there */
+ ret = dict_get_str (dict, "cgname", &cgname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "get neither volcount nor cgname");
+ goto out;
+ }
+ } else {
+ /* TODO: Change the index to 0 when mgmt v3 code is fixed */
+ ret = dict_get_str (dict, "volname1", &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "get volname");
+ goto out;
+ }
+ ret = dict_get_str (dict, "snapname", &snapname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "get snapname");
+ goto out;
+ }
+ }
+
+ if (NULL != cgname) {
+ cg = glusterd_find_snap_cg_by_name (conf, cgname);
+
+ if (NULL == cg) {
+ snprintf (err_str, len, "CG %s not found", cgname);
+ gf_log (this->name, GF_LOG_WARNING, "%s", err_str);
+ ret = -1;
+ goto out;
+ }
+
+ LOCK (&cg->lock);
+ {
+ /* Get the volumes belong to CG */
+ ret = glusterd_get_cg_volume_names_lk (dict, cg);
+ }
+ UNLOCK (&cg->lock);
+
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "volume names of %s CG", cgname);
+ goto out;
+ }
+ }
+
+ ret = glusterd_mgmt_v3_initiate_snap_phases (req, op, dict);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to initiate snap "
+ "phases");
+ goto out;
+ }
+
+ ret = 0; /* Success */
+
+out:
+ return ret;
+}
+
+int
+glusterd_snapshot_remove_prevalidate (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict)
+{
+ int32_t ret = -1;
+ char *volname = NULL;
+ char *name = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_snap_t *snap = NULL;
+ glusterd_snap_cg_t *cg = NULL;
+ char volname_buf[PATH_MAX] = {0, };
+ glusterd_volinfo_t *volinfo = NULL;
+ char err_str[PATH_MAX] = {0, };
+ int64_t volcount = 0;
+ int64_t i = 0;
+ int64_t j = 0;
+ gf_boolean_t volume_found = _gf_false;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+ GF_ASSERT (op_errstr);
+
+ if (!dict) {
+ gf_log (this->name, GF_LOG_ERROR, "input dict is NULL");
+ goto out;
+ }
+
+ ret = dict_get_int64 (dict, "volcount", &volcount);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting volcount failed");
+ goto out;
+ }
+
+ /* TODO: The policy for the snapshot create is not decided on
+ whether to start the snap volume upon the execution of the
+ snapshot create command. Once the policy is decided, check
+ here whether the volume is in use before delete command is
+ executed. (May be a force option to delete forcefully even
+ when the snap volume is in use.)
+ */
+
+ if (volcount > 1) {
+ ret = dict_get_str (dict, "cgname", &name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting the cg name"
+ " failed");
+ goto out;
+ }
+ cg = glusterd_find_snap_cg_by_name (conf, name);
+ if (!cg) {
+ snprintf (err_str, sizeof (err_str), "consistency group"
+ "%s is not found", name);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ *op_errstr = gf_strdup (err_str);
+ goto out;
+ }
+ GF_ASSERT (volcount == cg->volume_count);
+
+ for (i = 0; i < volcount; i++) {
+ volume_found = _gf_false;
+ snprintf (volname_buf, sizeof (volname_buf),
+ "volname%ld", i+1);
+ ret = dict_get_str (dict, volname_buf, &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "volume name "
+ "is notgiven");
+ goto out;
+ }
+ for (j = 0; j < volcount; j++) {
+ volinfo = cg->volumes[j];
+ if (!strcmp (volinfo->volname, volname)) {
+ volume_found = _gf_true;
+ break;
+ }
+ }
+ if (!volume_found) {
+ gf_log (this->name, GF_LOG_ERROR, "volume %s"
+ " is not found in the consistency "
+ "group %s", volname, name);
+ goto out;
+ }
+ }
+ } else {
+ snprintf (volname_buf, sizeof (volname_buf), "volname1");
+ ret = dict_get_str (dict, volname_buf, &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "volume name is not "
+ "given");
+ goto out;
+ }
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get the volinfo for "
+ "the volume %s", volname);
+ goto out;
+ }
+ ret = dict_get_str (dict, "snapname", &name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting snap name "
+ "failed (volume: %s)", volname);
+ goto out;
+ }
+ snap = glusterd_find_snap_by_name (volinfo, name);
+ if (!snap) {
+ ret = -1;
+ snprintf (err_str, sizeof (err_str), "snap %s is not "
+ "found", name);
+ gf_log (this->name, GF_LOG_ERROR, "%s, (volume: %s)",
+ err_str, volinfo->volname);
+ *op_errstr = gf_strdup (err_str);
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+glusterd_remove_snap (glusterd_brickinfo_t *brickinfo, const char *mount_pt,
+ const char *volname, const char *snapname,
+ const char *snap_device)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ runner_t runner = {0,};
+ char msg[1024] = {0, };
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ if (!brickinfo) {
+ gf_log (this->name, GF_LOG_ERROR, "brickinfo NULL");
+ goto out;
+ }
+
+ GF_ASSERT (mount_pt);
+ GF_ASSERT (volname);
+ GF_ASSERT (snapname);
+ GF_ASSERT (snap_device);
+
+ /* sleep for some time so that the glusterfsd process associated
+ with the snap lvm does not have any reference to the snap and
+ has been stopped completely
+ TODO: find the issue because of which umount fails and fix it.
+ */
+ //usleep (24007);
+
+ //ret = umount2 (mount_pt, MNT_FORCE);
+ runinit (&runner);
+ snprintf (msg, sizeof (msg), "umount the snapshot mounted path %s",
+ mount_pt);
+ runner_add_args (&runner, "umount", mount_pt, NULL);
+ runner_log (&runner, "", GF_LOG_DEBUG, msg);
+
+ /* We need not do synclock_unlock => runner_run => synclock_lock here.
+ Because it is needed if we are running a glusterfs process in
+ runner_run, so that when the glusterfs process started wants to
+ communicate to glusterd, glusterd wont be able to respond if it
+ has held the big lock. So we do unlock, run glusterfs process
+ (thus communicate to glusterd), lock. But since this is not a
+ glusterfs command that is being run, unlocking and then relocking
+ is not needed.
+ */
+ ret = runner_run (&runner);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "unmounting the "
+ "path %s (brick: %s) failed (%s)", mount_pt,
+ brickinfo->path, strerror (errno));
+ goto out;
+ }
+
+ runinit (&runner);
+ snprintf (msg, sizeof(msg), "remove snapshot of the brick %s:%s, "
+ "device: %s", brickinfo->hostname, brickinfo->path,
+ snap_device);
+ runner_add_args (&runner, "/sbin/lvremove", "-f", snap_device, NULL);
+ runner_log (&runner, "", GF_LOG_DEBUG, msg);
+
+ ret = runner_run (&runner);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "removing snapshot of the "
+ "brick (%s:%s) of device %s failed",
+ brickinfo->hostname, brickinfo->path, snap_device);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int32_t
+glusterd_brick_snapshot_remove (glusterd_volinfo_t *snap_volinfo,
+ glusterd_volinfo_t *actual_volinfo, char *name)
+{
+ char *mnt_pt = NULL;
+ struct mntent *entry = NULL;
+ int32_t ret = -1;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ xlator_t *this = NULL;
+ FILE *mtab = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!snap_volinfo) {
+ gf_log (this->name, GF_LOG_ERROR, "snap volinfo is NULL");
+ goto out;
+ }
+
+ if (!actual_volinfo) {
+ gf_log (this->name, GF_LOG_ERROR, "volinfo for the volume "
+ "is NULL");
+ goto out;
+ }
+
+ if (!name) {
+ gf_log (this->name, GF_LOG_ERROR, "snapname is NULL "
+ "(volume: %s)", actual_volinfo->volname);
+ goto out;
+ }
+
+ list_for_each_entry (brickinfo, &snap_volinfo->bricks, brick_list) {
+ if (uuid_compare (brickinfo->uuid, MY_UUID))
+ continue;
+
+ ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "getting the root "
+ "of the brick for snap volume %s faile", name);
+ goto out;
+ }
+
+ entry = glusterd_get_mnt_entry_info (mnt_pt, mtab);
+ if (!entry) {
+ gf_log (this->name, GF_LOG_WARNING, "getting the mount"
+ " entry for the brick %s:%s of the snap %s "
+ "(volume: %s) failed", brickinfo->hostname,
+ brickinfo->path, name, actual_volinfo->volname);
+ ret = -1;
+ goto out;
+ }
+ ret = glusterd_remove_snap (brickinfo, mnt_pt,
+ actual_volinfo->volname,
+ name, entry->mnt_fsname);
+ if (mtab)
+ endmntent (mtab);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "remove the snapshot %s (%s)",
+ brickinfo->path, entry->mnt_fsname);
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int32_t
+glusterd_do_snap_remove (glusterd_volinfo_t *volinfo, char *name)
+{
+ int32_t ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_snap_t *snap = NULL;
+ glusterd_volinfo_t *snap_volinfo = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ if (!volinfo) {
+ gf_log (this->name, GF_LOG_ERROR, "volinfo NULL");
+ goto out;
+ }
+
+ if (!name) {
+ gf_log (this->name, GF_LOG_ERROR, "name is NULL (volume: %s)",
+ volinfo->volname);
+ goto out;
+ }
+
+ snap = glusterd_find_snap_by_name (volinfo, name);
+ if (!snap) {
+ gf_log (this->name, GF_LOG_ERROR, "could not find "
+ "the snap object by the name %s",
+ name);
+ goto out;
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG, "found the snap %s "
+ "(volume: %s)", name, volinfo->volname);
+ }
+
+ snap_volinfo = snap->snap_volume;
+ GF_ASSERT (snap_volinfo);
+ list_for_each_entry (brickinfo, &snap_volinfo->bricks, brick_list) {
+ if (uuid_compare (brickinfo->uuid, MY_UUID))
+ continue;
+
+ /* TODO: The policy for the snapshot create is not
+ decided on whether to start the snap volume upon
+ the execution of the snapshot create command. Once
+ the policy is decided, check here whether the volume
+ is in use before delete command is executed.
+ (May be a force option to delete forcefully even
+ when the snap volume is in use.)
+ */
+ ret = glusterd_snap_brick_stop (volinfo, snap_volinfo,
+ brickinfo,
+ _gf_false);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "stopping "
+ "the brick %s:%s for the snap %s "
+ "(volume: %s) failed",
+ brickinfo->hostname,
+ brickinfo->path, snap_volinfo->volname,
+ volinfo->volname);
+ //goto out;
+ }
+ }
+ ret = glusterd_brick_snapshot_remove (snap_volinfo, volinfo,
+ name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "removing the bricks"
+ " snapshots for the snap %s (volume: %s) "
+ "failed", name, volinfo->volname);
+ goto out;
+ }
+
+ ret = glusterd_store_delete_volume (volinfo, snap->snap_volume);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "removing the snap "
+ "store for the snap %s (volume %s) failed",
+ snap->snap_name, volinfo->volname);
+ goto out;
+ }
+
+ snap = glusterd_remove_snap_by_name (volinfo, snap->snap_name);
+ GF_ASSERT (snap); //snap cannot be NULL;
+ glusterd_snap_delete (snap); //deletes in memory snap object
+
+ ret = glusterd_store_perform_snap_list_store (volinfo);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "doing the snap "
+ "store for the volume %s failed",
+ volinfo->volname);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+char *
+glusterd_get_snap_from_cg (glusterd_volinfo_t *volinfo, glusterd_snap_cg_t *cg)
+{
+ char *snap_name = NULL;
+ glusterd_snap_t *tmp_snap = NULL;
+ glusterd_snap_t *snap = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!volinfo) {
+ gf_log (this->name, GF_LOG_WARNING, "volinfo NULL");
+ goto out;
+ }
+
+ if (!cg) {
+ gf_log (this->name, GF_LOG_WARNING, "consistency group NULL");
+ goto out;
+ }
+
+ list_for_each_entry (tmp_snap, &volinfo->snaps, snap_list) {
+ if ((!uuid_is_null (tmp_snap->cg_id)) &&
+ (uuid_compare (tmp_snap->cg_id, cg->cg_id) == 0)) {
+ snap = tmp_snap;
+ break;
+ }
+ }
+
+ if (snap)
+ snap_name = gf_strdup (snap->snap_name);
+
+out:
+ return snap_name;
+}
+
+int32_t
+glusterd_snapshot_remove_commit (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict)
+{
+ int32_t ret = -1;
+ char *cg_name = NULL;
+ char *name = NULL;
+ glusterd_snap_cg_t *cg = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char *volname = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+ int64_t volcount = -1;
+ char volname_buf[PATH_MAX] = {0, };
+ int i = 0;
+ gf_boolean_t free_name = _gf_false;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ if (!dict || !op_errstr) {
+ gf_log (this->name, GF_LOG_ERROR, "input parameters NULL");
+ goto out;
+ }
+
+ ret = dict_get_int64 (dict, "volcount", &volcount);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "volume count not given");
+ goto out;
+ }
+
+ if (volcount > 1) {
+ ret = dict_get_str (dict, "cgname", &cg_name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting the cg name"
+ " failed");
+ goto out;
+ }
+ cg = glusterd_find_snap_cg_by_name (conf, cg_name);
+ if (!cg) {
+ gf_log (this->name, GF_LOG_ERROR, "consistency group "
+ "%s not found", cg_name);
+ goto out;
+ }
+ GF_ASSERT (volcount == cg->volume_count);
+ }
+
+ for (i = 0; i < volcount; i++) {
+ snprintf (volname_buf, sizeof (volname_buf), "volname%d", i+1);
+ ret = dict_get_str (dict, volname_buf, &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting volume name"
+ "failed");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "getting the volinfo"
+ " failed for the volume %s", volname);
+ goto out;
+ }
+ ret = dict_get_str (dict, "snapname", &name);
+ if (ret && volcount == 1) {
+ gf_log (this->name, GF_LOG_ERROR, "getting the snap "
+ "name failed (volume: %s)", volinfo->volname);
+ goto out;
+ }
+
+ if (!name) {
+ name = glusterd_get_snap_from_cg (volinfo, cg);
+ if (!name) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "get the snap name "
+ "(volname: %s, cg name: %s)",
+ volinfo->volname, cg->cg_name);
+ goto out;
+ }
+ free_name = _gf_true;
+ }
+
+ ret = glusterd_do_snap_remove (volinfo, name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "removing the %s %s failed",
+ (volinfo)?"snap":"cg", name);
+ goto out;
+ }
+ if (free_name)
+ GF_FREE (name);
+ name = NULL;
+ }
+
+ if (volcount > 1) {
+ ret = glusterd_store_delete_snap_cg (cg);
+ /* TODO: Handle the errors of deleting store handle of cg.
+ For now, the error is ignored and we proceed with the
+ deletion of the in memory cg object.
+ */
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING, "removing the "
+ "store handle for the consistency group %s "
+ "failed", cg->cg_name);
+ cg = glusterd_remove_snap_cg_by_name (conf, cg_name);
+ ret = glusterd_cg_delete (cg);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "removing the cg "
+ "object failed");
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ if (free_name)
+ GF_FREE (name);
+ return ret;
+}
+
/* name can be either the snapname if @volnames contains only one volume or
cg name if there are multiple volume names in volnames string
*/
@@ -3615,6 +4225,16 @@ glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
rsp_dict);
break;
+ case GF_SNAP_OPTION_TYPE_DELETE:
+ ret = glusterd_snapshot_remove_commit (dict, op_errstr,
+ rsp_dict);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "delete snapshot");
+ goto out;
+ }
+ break;
+
case GF_SNAP_OPTION_TYPE_RESTORE:
ret = glusterd_snapshot_restore (dict, op_errstr);
if (ret) {
@@ -3701,6 +4321,74 @@ out:
}
int
+glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict)
+{
+ int snap_command = 0;
+ xlator_t *this = NULL;
+ int ret = -1;
+
+ this = THIS;
+
+ GF_ASSERT (this);
+ GF_ASSERT (dict);
+ GF_ASSERT (rsp_dict); //not sure if this is needed, verify.
+
+ ret = dict_get_int32 (dict, "type", &snap_command);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "unable to get the type of "
+ "the snapshot command");
+ goto out;
+ }
+
+ switch (snap_command) {
+ case (GF_SNAP_OPTION_TYPE_CREATE):
+ ret = glusterd_snapshot_create_prevalidate (dict, op_errstr,
+ rsp_dict);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Snapshot create "
+ "pre-validation failed");
+ goto out;
+ }
+ break;
+
+ case (GF_SNAP_OPTION_TYPE_CONFIG):
+ ret = glusterd_snapshot_config_prevalidate (dict, op_errstr);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Snapshot config "
+ "pre-validation failed");
+ goto out;
+ }
+ break;
+
+ case GF_SNAP_OPTION_TYPE_RESTORE:
+ ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Snapshot restore "
+ "validation failed");
+ goto out;
+ }
+ break;
+ case GF_SNAP_OPTION_TYPE_DELETE:
+ ret = glusterd_snapshot_remove_prevalidate (dict, op_errstr,
+ rsp_dict);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Snapshot remove "
+ "validation failed");
+ goto out;
+ }
+ break;
+ default:
+ gf_log (this->name, GF_LOG_WARNING, "invalid snap command");
+ goto out;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
glusterd_handle_snapshot_fn (rpcsvc_request_t *req)
{
int32_t ret = 0;
@@ -3797,6 +4485,14 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req)
ret = glusterd_mgmt_v3_initiate_all_phases (req, cli_op, dict);
break;
case GF_SNAP_OPTION_TYPE_DELETE:
+ ret = glusterd_handle_snapshot_remove (req, cli_op, dict,
+ err_str,
+ sizeof (err_str));
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Snapshot delete "
+ "failed: %s", err_str);
+ }
+ break;
case GF_SNAP_OPTION_TYPE_START:
case GF_SNAP_OPTION_TYPE_STOP:
case GF_SNAP_OPTION_TYPE_STATUS:
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 9492baf3a..e9df28b8f 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -1688,6 +1688,52 @@ glusterd_brick_unlink_socket_file (glusterd_volinfo_t *volinfo,
}
int32_t
+glusterd_snap_brick_unlink_socket_file (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo)
+{
+ char path[PATH_MAX] = {0,};
+ char socketpath[PATH_MAX] = {0};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ int ret = 0;
+ char sock_filepath[PATH_MAX] = {0, };
+ int expected_file_len = 0;
+ char export_path[PATH_MAX] = {0,};
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (snap_volinfo);
+ GF_ASSERT (brickinfo);
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ GLUSTERD_GET_SNAP_DIR (path, volinfo, snap_volinfo->volname, priv);
+
+ glusterd_set_socket_filepath (sock_filepath, socketpath, sizeof (socketpath));
+
+ expected_file_len = strlen (GLUSTERD_SOCK_DIR) + strlen ("/") +
+ MD5_DIGEST_LENGTH*2 + strlen (".socket") + 1;
+ GF_ASSERT (sizeof (socketpath) >= expected_file_len);
+
+ GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, export_path);
+ snprintf (sock_filepath, PATH_MAX, "%s/run/%s-%s",
+ path, brickinfo->hostname, export_path);
+
+ ret = unlink (socketpath);
+ if (ret && (ENOENT == errno)) {
+ ret = 0;
+ } else {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to remove %s"
+ " error: %s", socketpath, strerror (errno));
+ }
+
+ return ret;
+}
+
+int32_t
glusterd_brick_disconnect (glusterd_brickinfo_t *brickinfo)
{
rpc_clnt_t *rpc = NULL;
@@ -1749,6 +1795,49 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo,
}
int32_t
+glusterd_snap_volume_stop_glusterfs (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ gf_boolean_t del_brick)
+{
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ char pidfile[PATH_MAX] = {0,};
+ int ret = 0;
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (brickinfo);
+ GF_ASSERT (snap_volinfo);
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ if (del_brick)
+ list_del_init (&brickinfo->brick_list);
+
+ if (GLUSTERD_STATUS_STARTED == volinfo->status) {
+ (void) glusterd_brick_disconnect (brickinfo);
+ GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo,
+ snap_volinfo->volname,
+ brickinfo, priv);
+ ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false);
+ if (ret == 0) {
+ glusterd_set_brick_status (brickinfo, GF_BRICK_STOPPED);
+ (void) glusterd_snap_brick_unlink_socket_file (volinfo,
+ snap_volinfo,
+ brickinfo);
+ }
+ }
+
+ if (del_brick)
+ glusterd_delete_snap_brick (volinfo, snap_volinfo, brickinfo);
+
+ return ret;
+}
+
+int32_t
glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name)
{
glusterd_peer_hostname_t *peer_hostname = NULL;
@@ -5358,6 +5447,60 @@ out:
}
int
+glusterd_snap_brick_stop (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ gf_boolean_t del_brick)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ if ((!brickinfo) || (!volinfo) || !snap_volinfo) {
+ gf_log (this->name, GF_LOG_ERROR, "input parameters NULL");
+ goto out;
+ }
+
+ if (uuid_is_null (brickinfo->uuid)) {
+ ret = glusterd_resolve_brick (brickinfo);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_RESOLVE_BRICK,
+ brickinfo->hostname, brickinfo->path);
+ goto out;
+ }
+ }
+
+ if (uuid_compare (brickinfo->uuid, MY_UUID)) {
+ ret = 0;
+ if (del_brick)
+ glusterd_delete_snap_brick (volinfo, snap_volinfo,
+ brickinfo);
+ goto out;
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG, "About to stop glusterfs"
+ " for brick %s:%s", brickinfo->hostname,
+ brickinfo->path);
+ ret = glusterd_snap_volume_stop_glusterfs (volinfo, snap_volinfo,
+ brickinfo, del_brick);
+ if (ret) {
+ gf_log (this->name, GF_LOG_CRITICAL, "Unable to stop"
+ " brick: %s:%s", brickinfo->hostname,
+ brickinfo->path);
+ goto out;
+ }
+
+out:
+ gf_log (this->name, GF_LOG_TRACE, "returning %d ", ret);
+ return ret;
+}
+
+int
glusterd_is_defrag_on (glusterd_volinfo_t *volinfo)
{
return (volinfo->rebal.defrag != NULL);
@@ -6006,6 +6149,49 @@ glusterd_delete_brick (glusterd_volinfo_t* volinfo,
}
int32_t
+glusterd_delete_snap_brick (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo)
+{
+ int ret = 0;
+ char voldir[PATH_MAX] = {0,};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (snap_volinfo);
+ GF_ASSERT (brickinfo);
+
+ GLUSTERD_GET_SNAP_DIR(voldir, volinfo, snap_volinfo->volname, priv);
+
+ ret = glusterd_delete_snap_volfile (volinfo, snap_volinfo, brickinfo);
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING, "failed to delete the "
+ "volfile for the brick (%s:%s), snap: %s volume: %s",
+ brickinfo->hostname, brickinfo->path,
+ snap_volinfo->volname, volinfo->volname);
+ ret = glusterd_store_delete_brick (brickinfo, voldir);
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING, "failed to delete the "
+ "store handle of brick (%s:%s), snap: %s volume: %s",
+ brickinfo->hostname, brickinfo->path,
+ snap_volinfo->volname, volinfo->volname);
+ ret = glusterd_brickinfo_delete (brickinfo);
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING, "failed to delete the "
+ "brickinfo (%s:%s), snap: %s volume: %s",
+ brickinfo->hostname, brickinfo->path,
+ snap_volinfo->volname, volinfo->volname);
+ snap_volinfo->brick_count--;
+ return ret;
+}
+
+int32_t
glusterd_delete_all_bricks (glusterd_volinfo_t* volinfo)
{
int ret = 0;
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index ca3c620aa..4c98559c9 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -292,6 +292,11 @@ glusterd_snap_brick_start (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
gf_boolean_t wait);
int
+glusterd_snap_brick_stop (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ gf_boolean_t del_brick);
+int
glusterd_is_defrag_on (glusterd_volinfo_t *volinfo);
int32_t
@@ -374,6 +379,10 @@ int32_t
glusterd_delete_brick (glusterd_volinfo_t* volinfo,
glusterd_brickinfo_t *brickinfo);
int32_t
+glusterd_delete_snap_brick (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo);
+int32_t
glusterd_delete_all_bricks (glusterd_volinfo_t* volinfo);
int
glusterd_spawn_daemons (void *opaque);
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index 50beb23f7..1bc0db6ce 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -3704,6 +3704,39 @@ glusterd_delete_volfile (glusterd_volinfo_t *volinfo,
}
int
+glusterd_delete_snap_volfile (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo)
+{
+ int ret = 0;
+ char filename[PATH_MAX] = {0,};
+ char brick[PATH_MAX] = {0, };
+ char path[PATH_MAX] = {0, };
+ glusterd_conf_t *priv = NULL;
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (brickinfo);
+ GF_ASSERT (snap_volinfo);
+
+ priv = THIS->private;
+ GF_ASSERT (priv);
+
+ GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, brick);
+ GLUSTERD_GET_SNAP_DIR (path, volinfo, snap_volinfo->volname, priv);
+
+ snprintf (filename, PATH_MAX, "%s/%s.%s.%s.vol",
+ path, snap_volinfo->volname,
+ brickinfo->hostname,
+ brick);
+
+ ret = unlink (filename);
+ if (ret)
+ gf_log ("glusterd", GF_LOG_ERROR, "failed to delete file: %s, "
+ "reason: %s", filename, strerror (errno));
+ return ret;
+}
+
+int
validate_shdopts (glusterd_volinfo_t *volinfo,
dict_t *val_dict,
char **op_errstr)
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h
index dc334ca8d..2b22f5226 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.h
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h
@@ -124,6 +124,10 @@ int glusterd_create_shd_volfile ();
int glusterd_delete_volfile (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo);
+int
+glusterd_delete_snap_volfile (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo,
+ glusterd_brickinfo_t *brickinfo);
int glusterd_volinfo_get (glusterd_volinfo_t *volinfo, char *key, char **value);
int glusterd_volinfo_get_boolean (glusterd_volinfo_t *volinfo, char *key);