snapshot: append timestamp with snapname

Appending GMT time stamp with snapname by default.
If no-timestamp flag is given during snapshot creation,
then time stamp will not append with snapname;

Initial consumer of this feature is Samba's Shadow Copy
feature. This feature allows Windows user to get previous 
revisions of a file. For this feature to work snapshot 
names under .snaps folder (USS) should have timestamp in 
following format appended:
@GMT-YYYY.MM.DD-hh.mm.ss

PS: https://www.samba.org/samba/docs/man/manpages/vfs_shadow_copy2.8.html

This format is configurable by Samba conf file. Due to a 
limitation in Windows directory access the exact format 
cannot be used by USS. Therefore we have modified the file 
format to:
_GMT-YYYY.MM.DD-hh.mm.ss

Snapshot scheduling feature also required to append timestamp 
to the snapshot name therefore timestamp is appended in 
snapshot creation itself instead of doing the changes in 
snapview server.

More info:
https://www.mail-archive.com/gluster-users@gluster.org/msg18895.html

Change-Id: Idac24670948cf4c0fbe916ea6690e49cbc832d07
BUG: 1189473
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
Reviewed-on: http://review.gluster.org/9597
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
This commit is contained in:
Mohammed Rafi KC 2015-02-05 16:12:53 +05:30 committed by Krishnan Parthasarathi
parent 8cdd272dcf
commit 1ae8b4c33a
21 changed files with 127 additions and 70 deletions

View File

@ -3397,7 +3397,9 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount) {
/* Filling volume name in the dictionary */
for (i = cmdi + 1 ; i < wordcount
&& (strcmp (words[i], "description")) != 0
&& (strcmp (words[i], "force") != 0); i++) {
&& (strcmp (words[i], "force") != 0)
&& (strcmp (words[i], "no-timestamp") != 0);
i++) {
volcount++;
/* volume index starts from 1 */
ret = snprintf (key, sizeof (key), "volname%"PRIu64, volcount);
@ -3437,13 +3439,24 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount) {
/* Verify how we got out of "for" loop,
* if it is by reaching wordcount limit then goto "out",
* because we need not parse for "description" and "force"
* after this.
* because we need not parse for "description","force" and
* "no-timestamp" after this.
*/
if (i == wordcount) {
goto out;
}
if (strcmp (words[i], "no-timestamp") == 0) {
ret = dict_set_str (dict, "no-timestamp", "true");
if (ret) {
gf_log ("cli", GF_LOG_ERROR, "Could not save "
"time-stamp option");
}
if (i == (wordcount-1))
goto out;
i++;
}
if ((strcmp (words[i], "description")) == 0) {
++i;
if (i > (wordcount - 1)) {
@ -4291,6 +4304,7 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options,
case GF_SNAP_OPTION_TYPE_CREATE:
/* Syntax :
* gluster snapshot create <snapname> <vol-name(s)>
* [no-timestamp]
* [description <description>]
* [force]
*/

View File

@ -82,7 +82,8 @@ struct cli_cmd snapshot_cmds[] = {
cli_cmd_snapshot_help_cbk,
"display help for snapshot commands"
},
{ "snapshot create <snapname> <volname(s)> [description <description>] [force]",
{ "snapshot create <snapname> <volname(s)> [no-timestamp] "
"[description <description>] [force]",
cli_cmd_snapshot_cbk,
"Snapshot Create."
},

View File

@ -43,11 +43,11 @@ for i in {1..10} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot config activate-on-create enable
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
for i in {11..20} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap2 $V0;
TEST $CLI snapshot create snap2 $V0 no-timestamp;
mkdir $M0/dir1;
mkdir $M0/dir2;
@ -55,13 +55,12 @@ mkdir $M0/dir2;
for i in {1..10} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {1..10} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap3 $V0;
TEST $CLI snapshot create snap3 $V0 no-timestamp;
for i in {11..20} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {11..20} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap4 $V0;
TEST $CLI snapshot create snap4 $V0 no-timestamp;
## Test that features.uss takes only options enable/disable and throw error for
## any other argument.
for i in {1..10}; do
@ -81,7 +80,6 @@ TEST ls $M0/.snaps;
NUM_SNAPS=$(ls $M0/.snaps | wc -l);
TEST [ $NUM_SNAPS == 4 ]
TEST ls $M0/.snaps/snap1;
TEST ls $M0/.snaps/snap2;
TEST ls $M0/.snaps/snap3;
@ -290,7 +288,7 @@ TEST fd_close $fd3;
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0
#test 131
TEST $CLI snapshot create snap5 $V0
TEST $CLI snapshot create snap5 $V0 no-timestamp
TEST ls $M0/.history;
function count_snaps
@ -319,7 +317,7 @@ EXPECT_WITHIN 30 "5" count_snaps $M0;
echo "aaa" > $M0/aaa;
TEST $CLI snapshot create snap6 $V0
TEST $CLI snapshot create snap6 $V0 no-timestamp
TEST ls $M0/.history;
@ -331,7 +329,7 @@ TEST rm -f $M0/aaa;
TEST $CLI snapshot delete snap6;
TEST $CLI snapshot create snap6 $V0
TEST $CLI snapshot create snap6 $V0 no-timestamp
TEST ls $M0/.history;

View File

@ -19,15 +19,25 @@ function create_volumes() {
}
function create_snapshots() {
$CLI_1 snapshot create ${V0}_snap ${V0}&
$CLI_1 snapshot create ${V0}_snap ${V0} no-timestamp &
PID_1=$!
$CLI_1 snapshot create ${V1}_snap ${V1}&
$CLI_1 snapshot create ${V1}_snap ${V1} no-timestamp &
PID_2=$!
wait $PID_1 $PID_2
}
function create_snapshots_with_timestamp() {
$CLI_1 snapshot create ${V0}_snap1 ${V0}&
PID_1=$!
$CLI_1 snapshot create ${V1}_snap1 ${V1}&
PID_2=$!
wait $PID_1 $PID_2
}
function activate_snapshots() {
$CLI_1 snapshot activate ${V0}_snap &
PID_1=$!
@ -49,10 +59,10 @@ function deactivate_snapshots() {
}
function delete_snapshots() {
$CLI_1 snapshot delete ${V0}_snap &
$CLI_1 snapshot delete $1 &
PID_1=$!
$CLI_1 snapshot delete ${V1}_snap &
$CLI_1 snapshot delete $2 &
PID_2=$!
wait $PID_1 $PID_2
@ -114,6 +124,15 @@ EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
TEST glusterfs -s $H2 --volfile-id=/snaps/${V1}_snap/${V1} $M0
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
#create timestamp appended snaps
create_snapshots_with_timestamp;
new_name1=`$CLI_1 snapshot list ${V0} | grep ${V0}_snap1`;
new_name2=`$CLI_1 snapshot list ${V1} | grep ${V1}_snap1`;
EXPECT_NOT "{V0}_snap1" echo $new_name1;
EXPECT_NOT "{V1}_snap1" echo $new_name1;
delete_snapshots $new_name1 $new_name2;
#Clean up
stop_force_volumes 2
EXPECT 'Stopped' volinfo_field $V0 'Status';

View File

@ -54,7 +54,7 @@ for i in {1..10} ; do echo "foo" > $M0/dir2/foo$i ; done
for i in {11..20} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {11..20} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
TEST $CLI snapshot activate snap1;
TEST $CLI volume set $V0 features.uss enable;

View File

@ -19,13 +19,13 @@ S2="-${V0}-snap2" #Create snapshot with name starts with hyphen(-)
#Create snapshot with a long name
S3="${V0}_single_gluster_volume_is_accessible_by_multiple_clients_offline_snapshot_is_a_long_name"
TEST $CLI snapshot create $S1 $V0
TEST $CLI snapshot create $S1 $V0 no-timestamp
TEST snapshot_exists 0 $S1
TEST $CLI snapshot create $S2 $V0
TEST $CLI snapshot create $S2 $V0 no-timestamp
TEST snapshot_exists 0 $S2
TEST $CLI snapshot create $S3 $V0
TEST $CLI snapshot create $S3 $V0 no-timestamp
TEST snapshot_exists 0 $S3

View File

@ -30,11 +30,11 @@ TEST snapshot_n_exists $V0 3 $V0_snap
#Creating the 4th snapshot on the volume and expecting it to be created
# but with the deletion of the oldest snapshot i.e 1st snapshot
TEST $CLI_1 snapshot create ${V0}_snap4 ${V0}
TEST $CLI_1 snapshot create ${V0}_snap4 ${V0} no-timestamp
TEST snapshot_exists 1 ${V0}_snap4
TEST ! snapshot_exists 1 ${V0}_snap1
TEST $CLI_1 snapshot delete ${V0}_snap4
TEST $CLI_1 snapshot create ${V0}_snap1 ${V0}
TEST $CLI_1 snapshot create ${V0}_snap1 ${V0} no-timestamp
TEST snapshot_exists 1 ${V0}_snap1
#Deleting the 4 snaps

View File

@ -16,11 +16,11 @@ TEST $CLI volume start $V0;
TEST kill_brick $V0 $H0 $L1;
#Normal snap create should fail
TEST ! $CLI snapshot create ${V0}_snap1 $V0;
TEST ! $CLI snapshot create ${V0}_snap1 $V0 no-timestamp;
TEST ! snapshot_exists 0 ${V0}_snap1;
#With changes introduced in BZ #1184344 force snap create should fail too
TEST ! $CLI snapshot create ${V0}_snap1 $V0 force;
TEST ! $CLI snapshot create ${V0}_snap1 $V0 no-timestamp force;
TEST ! snapshot_exists 0 ${V0}_snap1;
cleanup;

View File

@ -23,11 +23,11 @@ TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0;
for i in {1..10} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
for i in {11..20} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap2 $V0;
TEST $CLI snapshot create snap2 $V0 no-timestamp;
mkdir $M0/dir1;
mkdir $M0/dir2;
@ -35,12 +35,12 @@ mkdir $M0/dir2;
for i in {1..10} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {1..10} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap3 $V0;
TEST $CLI snapshot create snap3 $V0 no-timestamp;
for i in {11..20} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {11..20} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap4 $V0;
TEST $CLI snapshot create snap4 $V0 no-timestamp;
TEST $CLI volume set $V0 features.uss enable;

View File

@ -27,11 +27,11 @@ for i in {1..10} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot config activate-on-create enable
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
for i in {11..20} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap2 $V0;
TEST $CLI snapshot create snap2 $V0 no-timestamp;
mkdir $M0/dir1;
mkdir $M0/dir2;
@ -39,12 +39,12 @@ mkdir $M0/dir2;
for i in {1..10} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {1..10} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap3 $V0;
TEST $CLI snapshot create snap3 $V0 no-timestamp;
for i in {11..20} ; do echo "foo" > $M0/dir1/foo$i ; done
for i in {11..20} ; do echo "foo" > $M0/dir2/foo$i ; done
TEST $CLI snapshot create snap4 $V0;
TEST $CLI snapshot create snap4 $V0 no-timestamp;
TEST $CLI volume set $V0 features.uss enable;

View File

@ -34,7 +34,7 @@ TEST $CLI_1 volume create $V0 $H1:$L1 $H2:$L2
TEST $CLI_1 volume start $V0
#Create snapshot and add a peer together
$CLI_1 snapshot create ${V0}_snap1 ${V0} &
$CLI_1 snapshot create ${V0}_snap1 ${V0} no-timestamp &
PID_1=$!
$CLI_1 peer probe $H3
wait $PID_1

View File

@ -21,11 +21,11 @@ TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0;
for i in {1..10} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
for i in {11..20} ; do echo "file" > $M0/file$i ; done
TEST $CLI snapshot create snap2 $V0;
TEST $CLI snapshot create snap2 $V0 no-timestamp;
TEST $CLI volume stop $V0

View File

@ -20,7 +20,7 @@ TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0
# create 10 snapshots and check if all are being reflected
# in the USS world
gluster snapshot config activate-on-create enable
for i in {1..10}; do $CLI snapshot create snap$i $V0; done
for i in {1..10}; do $CLI snapshot create snap$i $V0 no-timestamp; done
EXPECT 10 uss_count_snap_displayed $M0
# snapshots should not be displayed after deactivation

View File

@ -13,11 +13,11 @@ TEST setup_lvm 1
TEST $CLI volume create $V0 $H0:$L1
TEST $CLI volume start $V0
TEST $CLI snapshot create snap1 $V0
TEST $CLI snapshot create snap1 $V0 no-timestamp
EXPECT 'Stopped' snapshot_status snap1;
TEST $CLI snapshot config activate-on-create enable
TEST $CLI snapshot create snap2 $V0
TEST $CLI snapshot create snap2 $V0 no-timestamp
EXPECT 'Started' snapshot_status snap2;
#Clean up

View File

@ -22,7 +22,7 @@ ln -s $M0/file1 $M0/test/file_symlink
ls -l $M0/ > /dev/null
ls -l $M0/test/ > /dev/null
TEST $CLI snapshot create snap1 $V0;
TEST $CLI snapshot create snap1 $V0 no-timestamp;
$CLI snapshot activate snap1;
EXPECT 'Started' snapshot_status snap1;

View File

@ -20,13 +20,13 @@ TEST glusterfs -s $H0 --volfile-id=$V0 $M0
TEST mkdir $M0/xyz
TEST $CLI snapshot create snap1 $V0
TEST $CLI snapshot create snap2 $V0
TEST $CLI snapshot create snap1 $V0 no-timestamp
TEST $CLI snapshot create snap2 $V0 no-timestamp
TEST rmdir $M0/xyz
TEST $CLI snapshot create snap3 $V0
TEST $CLI snapshot create snap4 $V0
TEST $CLI snapshot create snap3 $V0 no-timestamp
TEST $CLI snapshot create snap4 $V0 no-timestamp
TEST mkdir $M0/xyz
TEST ls $M0/xyz/.snaps/

View File

@ -16,7 +16,7 @@ TEST glusterfs -s $H0 --volfile-id=$V0 $M0
TEST touch $M0/testfile
TEST $CLI snapshot create snaps $V0
TEST $CLI snapshot create snaps $V0 no-timestamp
TEST $CLI snapshot activate snaps
TEST $CLI volume set $V0 features.uss enable
TEST $CLI volume set $V0 snapshot-directory snaps

View File

@ -23,8 +23,8 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'Started' volinfo_field $V0 'Status';
TEST mount_nfs $H0:/$V0 $N0 nolock
TEST mkdir $N0/testdir
TEST $CLI snapshot create snap1 $V0
TEST $CLI snapshot create snap2 $V0
TEST $CLI snapshot create snap1 $V0 no-timestamp
TEST $CLI snapshot create snap2 $V0 no-timestamp
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "0" STAT $N0/testdir/.snaps

View File

@ -93,7 +93,7 @@ chmod 700 $M0/README
# enable uss and take a snapshot
TEST $CLI volume set $V0 uss enable
TEST $CLI snapshot config activate-on-create on
TEST $CLI snapshot create snap1 $V0
TEST $CLI snapshot create snap1 $V0 no-timestamp
# try to access the file using user1 account.
# It should succeed with both normal mount and snapshot world.
@ -146,7 +146,7 @@ create_user $user5
chgrp $group3 $M0/file3
TEST $CLI snapshot create snap2 $V0
TEST $CLI snapshot create snap2 $V0 no-timestamp
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" check_if_permitted $user3 $M0/file3 cat
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" check_if_permitted $user3 $M0/.snaps/snap2/file3 cat

View File

@ -228,7 +228,7 @@ function create_n_snapshots() {
local snap_name=$3
local ret=0
for i in `seq 1 $snap_count`; do
$CLI_1 snapshot create $snap_name$i ${vol}&
$CLI_1 snapshot create $snap_name$i ${vol} no-timestamp &
PID_1=$!
wait $PID_1
ret=$?
@ -337,7 +337,7 @@ function snap_create()
while [ $i -lt $limit ]
do
$cli_index snapshot create snap$i $volname
$cli_index snapshot create snap$i $volname no-timestamp
i=$[$i+1]
done
}

View File

@ -3471,19 +3471,22 @@ int
glusterd_handle_snapshot_create (rpcsvc_request_t *req, glusterd_op_t op,
dict_t *dict, char *err_str, size_t len)
{
int ret = -1;
char *volname = NULL;
char *snapname = NULL;
int64_t volcount = 0;
xlator_t *this = NULL;
char key[PATH_MAX] = "";
char *username = NULL;
char *password = NULL;
uuid_t *uuid_ptr = NULL;
uuid_t tmp_uuid = {0};
int i = 0;
char snap_volname[GD_VOLUME_NAME_MAX] = {0, };
int ret = -1;
char *volname = NULL;
char *snapname = NULL;
int64_t volcount = 0;
xlator_t *this = NULL;
char key[PATH_MAX] = "";
char *username = NULL;
char *password = NULL;
uuid_t *uuid_ptr = NULL;
uuid_t tmp_uuid = {0};
int i = 0;
gf_boolean_t timestamp = _gf_false;
char snap_volname[GD_VOLUME_NAME_MAX] = {0, };
char new_snapname[GLUSTERD_MAX_SNAP_NAME] = {0, };
char gmt_snaptime[GLUSTERD_MAX_SNAP_NAME] = {0, };
time_t snap_time;
this = THIS;
GF_ASSERT (this);
GF_ASSERT (req);
@ -3509,6 +3512,34 @@ glusterd_handle_snapshot_create (rpcsvc_request_t *req, glusterd_op_t op,
goto out;
}
timestamp = dict_get_str_boolean (dict, "no-timestamp", _gf_false);
if (ret) {
gf_log (this->name, GF_LOG_DEBUG, "no-timestamp flag "
"is not set");
goto out;
}
ret = dict_set_int64 (dict, "snap-time", (int64_t)time(&snap_time));
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "Unable to set snap-time");
goto out;
}
if (!timestamp) {
strftime (gmt_snaptime, sizeof (gmt_snaptime),
"_GMT-%Y.%m.%d-%H.%M.%S", gmtime(&snap_time));
snprintf (new_snapname, sizeof (new_snapname), "%s%s",
snapname, gmt_snaptime);
ret = dict_set_dynstr_with_alloc (dict, "snapname",
new_snapname);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "Unable to update "
"snap-name");
goto out;
}
snapname = new_snapname;
}
if (strlen(snapname) >= GLUSTERD_MAX_SNAP_NAME) {
snprintf (err_str, len, "snapname cannot exceed 255 "
"characters");
@ -3533,12 +3564,6 @@ glusterd_handle_snapshot_create (rpcsvc_request_t *req, glusterd_op_t op,
}
uuid_ptr = NULL;
ret = dict_set_int64 (dict, "snap-time", (int64_t)time(NULL));
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "Unable to set snap-time");
goto out;
}
for (i = 1; i <= volcount; i++) {
snprintf (key, sizeof (key), "volname%d", i);
ret = dict_get_str (dict, key, &volname);