diff options
Diffstat (limited to 'tests/features')
26 files changed, 2101 insertions, 302 deletions
diff --git a/tests/features/delay-gen.t b/tests/features/delay-gen.t new file mode 100755 index 00000000000..72e6dbb7697 --- /dev/null +++ b/tests/features/delay-gen.t @@ -0,0 +1,52 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/${V0}1 + +EXPECT "$V0" volinfo_field $V0 'Volume Name' +EXPECT 'Created' volinfo_field $V0 'Status' + +TEST $CLI volume set $V0 delay-gen posix +TEST $CLI volume set $V0 delay-gen.delay-duration 1000000 +TEST $CLI volume set $V0 delay-gen.delay-percentage 100 +TEST $CLI volume set $V0 delay-gen.enable read,write + +TEST $CLI volume start $V0 +EXPECT 'Started' volinfo_field $V0 'Status' + +TEST $CLI volume profile $V0 start +## Mount FUSE with caching disabled (read-write) +TEST $GFS -s $H0 --volfile-id $V0 $M0 + +TEST dd if=/dev/zero of=$M0/1 count=1 bs=128k oflag=sync + +#Write should take at least a second +write_max_latency=$($CLI volume profile $V0 info | grep WRITE | awk 'BEGIN {max = 0} {if ($6 > max) max=$6;} END {print max}' | cut -d. -f 1 | egrep "[0-9]{7,}") + +#Create should not take a second +create_max_latency=$($CLI volume profile $V0 info | grep CREATE | awk 'BEGIN {max = 0} {if ($6 > max) max=$6;} END {print max}' | cut -d. -f 1 | egrep "[0-9]{7,}") + +TEST [ ! -z $write_max_latency ]; +TEST [ -z $create_max_latency ]; + +# Not providing a particular fop will make it test everything +TEST $CLI volume reset $V0 delay-gen.enable +TEST $CLI volume set $V0 delay-gen.delay-duration 100 + +cp $(dirname ${0})/../basic/gfapi/glfsxmp-coverage.c glfsxmp.c +build_tester ./glfsxmp.c -lgfapi +./glfsxmp $V0 $H0 >/dev/null +cleanup_tester ./glfsxmp +rm ./glfsxmp.c + +$(dirname $0)/../basic/rpc-coverage.sh $M0 >/dev/null + +cleanup; +#G_TESTDEF_TEST_STATUS_NETBSD7=1501397 diff --git a/tests/features/fdl-overflow.t b/tests/features/fdl-overflow.t new file mode 100644 index 00000000000..34b941d2f2a --- /dev/null +++ b/tests/features/fdl-overflow.t @@ -0,0 +1,72 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../fdl.rc + +_check_sizes () { + local n=0 + local sz + local total_sz=0 + + # We don't care about the sizes of the meta files. That would be + # embedding too much of the implementation into the test. + n=$(ls ${log_base}/${log_id}-meta-*.jnl | wc -l) + [ $n = 2 ] || return 1 + + # We *do* care about the sizes of the data files, which should exactly + # reflect the amount of data written via dd. + n=0 + while read sz name; do + G_LOG "found journal ${name} size ${sz}MB" + n=$((n+1)) + total_sz=$((total_sz+sz)) + done < <(du -sm ${log_base}/${log_id}-data-*.jnl) + [ $n = 2 ] || return 1 + # On our CentOS and NetBSD regression-test systems, but not on my Fedora + # development system, each file ends up being slightly larger than its + # data size because of metadata, and 'du' rounds that up to a full extra + # megabyte. We'll allow either result, because what we're really + # looking for is a complete failure to roll over from one file to + # another at the appropriate size. + [ $total_sz = 20 -o $total_sz = $((n+20)) ] || return 1 + + return 0 +} + +check_sizes () { + set -x + _check_sizes + ret=$? + set +x + return ret +} + +if [ x"$OSTYPE" = x"NetBSD" ]; then + CREAT_OFLAG="creat," +else + CREAT_OFLAG="" +fi + +TEST rm -f ${log_base}/${log_id}-*.log +TEST glusterd +TEST pidof glusterd + +# Get a simple volume set up and mounted with FDL active. +TEST $CLI volume create $V0 ${H0}:${B0}/${V0}-0 +TEST $CLI volume set $V0 changelog.changelog off +TEST $CLI volume set $V0 features.fdl on +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id $V0 $M0 + +# Generate some I/O and unmount/stop so we can see log sizes. +TEST dd if=/dev/zero of=$M0/twentyMB bs=1048576 count=20 \ + oflag=${CREAT_OFLAG}sync +TEST umount $M0 +TEST $CLI volume stop $V0 + +TEST _check_sizes + +cleanup +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1385758 +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=1385758 diff --git a/tests/features/fdl.t b/tests/features/fdl.t new file mode 100644 index 00000000000..5a3c13fc850 --- /dev/null +++ b/tests/features/fdl.t @@ -0,0 +1,44 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../fdl.rc + +if [ x"$OSTYPE" = x"NetBSD" ]; then + CREAT_OFLAG="creat," +else + CREAT_OFLAG="" +fi + +TEST rm -f $FDL_META_FILE $FDL_DATA_FILE +TEST glusterd +TEST pidof glusterd + +# Get a simple volume set up and mounted with FDL active. +TEST $CLI volume create $V0 ${H0}:${B0}/${V0}-0 +TEST $CLI volume set $V0 changelog.changelog off +TEST $CLI volume set $V0 features.fdl on +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id $V0 $M0 + +# Generate some I/O and unmount. +TEST mkdir -p $M0/abc/def +TEST dd if=/dev/zero of=$M0/abc/def/ghi bs=128 count=2 \ + oflag=${CREAT_OFLAG}sync +TEST chmod 314 $M0/abc/def/ghi +TEST rm -rf $M0/abc +TEST umount $M0 + +# Check that gf_logdump works, and shows the ops we just issued. There will be +# more SETATTR ops than the one corresponding to our chmod, because some are +# issued internally. We have to guess a bit about where the log will be. +TEST check_logfile GF_FOP_MKDIR 2 +TEST check_logfile GF_FOP_CREATE 1 +TEST check_logfile GF_FOP_WRITE 2 +TEST check_logfile GF_FOP_SETATTR 1 +TEST check_logfile GF_FOP_UNLINK 1 +TEST check_logfile GF_FOP_RMDIR 2 + +cleanup +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1385758 +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=1385758 diff --git a/tests/features/flock_interrupt.t b/tests/features/flock_interrupt.t new file mode 100644 index 00000000000..b8717e30dfb --- /dev/null +++ b/tests/features/flock_interrupt.t @@ -0,0 +1,32 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +## Start and create a volume +TEST glusterd; +TEST pidof glusterd; + +TEST $CLI volume create $V0 $H0:$B0/${V0}0; + +## Verify volume is is created +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +## Start volume and verify +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST touch $M0/testfile; + +echo > got_lock +flock $M0/testfile sleep 6 & { sleep 0.3; flock -w 2 $M0/testfile true; echo ok > got_lock; } & + +EXPECT_WITHIN 4 ok cat got_lock; + +## Finish up +rm -f got_lock; +cleanup; diff --git a/tests/features/fuse-lru-limit.t b/tests/features/fuse-lru-limit.t new file mode 100644 index 00000000000..dd6be2d5397 --- /dev/null +++ b/tests/features/fuse-lru-limit.t @@ -0,0 +1,43 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume start $V0 +TEST glusterfs -s $H0 --volfile-id $V0 $M0 +EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "2" online_brick_count + +EXPECT "1" get_mount_active_size_value $V0 $M0 +EXPECT "0" get_mount_lru_size_value $V0 $M0 + +mkdir ${M0}/dir-{1..9} +for i in {1..9}; do + for j in {1..1000}; do + echo "Test file" > ${M0}/dir-$i/file-$j; + done; +done +lc=$(get_mount_lru_size_value $V0 ${M0}) +# ideally it should be 9000+ +TEST [ $lc -ge 9000 ] + +TEST umount $M0 + +TEST glusterfs -s $H0 --volfile-id $V0 --lru-limit 1000 $M0 + +TEST find $M0 +lc=$(get_mount_lru_size_value $V0 ${M0}) +# ideally it should be <1000 +# Not sure if there are any possibilities of buffer need. +TEST [ $lc -le 1000 ] + +TEST rm -rf $M0/* + +EXPECT "1" get_mount_active_size_value $V0 $M0 +EXPECT "0" get_mount_lru_size_value $V0 $M0 + +cleanup diff --git a/tests/features/glfs-lease-recall.c b/tests/features/glfs-lease-recall.c new file mode 100644 index 00000000000..9a60f9beec1 --- /dev/null +++ b/tests/features/glfs-lease-recall.c @@ -0,0 +1,372 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +/* Few rules: + * 1. A client may have multiple lease keys, but a lease key cannot be shared by + * multiple clients. + * 2. Lease key can be set before open, or in glfs_lease request. A lease key + * set like this is valid for the lifetime of the fd, i.e. a fd cannot have + * multiple lease key. But a lease key can be shared across multiple fds. + */ +glfs_t *client1 = NULL, *client2 = NULL; +glfs_fd_t *fd1 = NULL; +FILE *log_file = NULL; +char lid1[GLFS_LEASE_ID_SIZE] = "lid1-clnt1", + lid2[GLFS_LEASE_ID_SIZE] = "lid2-clnt2"; +char lid3[GLFS_LEASE_ID_SIZE] = "lid3-clnt2", lid4[GLFS_LEASE_ID_SIZE] = { + 0, +}; +char *volname = NULL, *glfs_log_file = NULL; +int upcall_recv = 0; + +#define MAX_CLIENTS 4 +#define MAX_FDS 4 +#define TEST_FILE "/test/lease" +#define SHUD_PASS 0 +#define SHUD_FAIL -1 +#define NONE 0 + +static void +recall_cbk(struct glfs_lease lease, void *data); + +static int +set_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, fd); + if (ret < 0) { + fprintf(log_file, "\n RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RD_LEASE"); + return ret; +} + +static int +set_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n RW_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RW_LEASE"); + return ret; +} + +static int +get_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_GET_LEASE; + lease.lease_type = -1; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n GET_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + if (lease.lease_type == GLFS_RD_LEASE) + fprintf(log_file, "\n Esisting Lease: RD_LEASE"); + else if (lease.lease_type == GLFS_RW_LEASE) + fprintf(log_file, "\n Esisting Lease: RW_LEASE"); + else if (lease.lease_type == 3) + fprintf(log_file, "\n Esisting Lease: RD_LEASE|RW_LEASE"); + else if (lease.lease_type == 0) + fprintf(log_file, "\n Esisting Lease: NONE"); + else + fprintf(log_file, "\n Existing lease type:%d", lease.lease_type); + return lease.lease_type; +} + +static int +unlk_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RW_LESAE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RW_LEASE"); + return ret; +} + +static int +unlk_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RD_LEASE"); + return ret; +} + +void +up_async_lease_recall(struct glfs_upcall *up_arg, void *data) +{ + struct glfs_upcall_lease *in_arg = NULL; + enum glfs_upcall_reason reason = 0; + struct glfs_object *object = NULL; + uint64_t flags = 0; + uint64_t expire = 0; + + if (!up_arg) + return; + + reason = glfs_upcall_get_reason(up_arg); + + /* Expect 'GLFS_UPCALL_RECALL_LEASE' upcall event. */ + + if (reason == GLFS_UPCALL_RECALL_LEASE) { + in_arg = glfs_upcall_get_event(up_arg); + + object = glfs_upcall_lease_get_object(in_arg); + + fprintf(log_file, + " upcall event type - %d," + " object(%p)\n", + reason, object); + upcall_recv = 1; + } + + glfs_free(up_arg); + return; +} + +glfs_t * +setup_new_client(char *volname, char *log_fileile) +{ + int ret = 0; + glfs_t *fs = NULL; + int up_events = GLFS_EVENT_ANY; + + fs = glfs_new(volname); + if (!fs) { + fprintf(log_file, "\nglfs_new: returned NULL (%s)\n", strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_fileile, 7); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(log_file, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + /* Register Upcalls */ + ret = glfs_upcall_register(fs, up_events, up_async_lease_recall, NULL); + + /* Check if the return mask contains the event */ + if ((ret < 0) || !(ret & GLFS_EVENT_RECALL_LEASE)) { + fprintf(stderr, + "glfs_upcall_register return doesn't contain" + " upcall event - GLFS_EVENT_RECALL_LEASE\n"); + goto error; + } + + return fs; +error: + if (fs) + glfs_fini(fs); + return NULL; +} + +#define OPEN(client, flags, fd, lease_id) \ + do { \ + int ret_val = 0; \ + ret_val = glfs_setfsleaseid(lease_id); \ + if (ret_val) { \ + fprintf(log_file, \ + "\nglfs_setfsleaseid failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + fd = glfs_open(client, TEST_FILE, flags); \ + if (fd == NULL) { \ + fprintf(log_file, "\nglfs_open failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + } while (0) + +#define VERIFY_RESULT(test_case, ret, value) \ + do { \ + if (ret != value) { \ + fprintf(log_file, \ + "\n Testcase %d failed, ret = %d, value=%d\n", \ + test_case, ret, value); \ + goto error; /*test unsuccessful*/ \ + } \ + fprintf(log_file, "\n Testcase %d Succeeded\n", test_case); \ + } while (0) + +static void +recall_cbk(struct glfs_lease lease, void *data) +{ + int ret = -1; + char ld[GLFS_LEASE_ID_SIZE] = ""; + + fprintf(log_file, "\nRECALL received on lease_id:(%s)", lease.lease_id); + memcpy(ld, lease.lease_id, GLFS_LEASE_ID_SIZE); + ret = unlk_write_lease((glfs_fd_t *)data, ld); + VERIFY_RESULT(500, ret, SHUD_PASS); +error: + return; +} + +static int +testcase_recall_conflict_lease() +{ + struct glfs_object *obj = NULL; + glfs_fd_t *fd1 = NULL; + int ret = 0; + struct glfs_lease lease = { + 0, + }; + + fprintf(log_file, + "\n Basic test case for conflicting lease causing recall"); + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, lid2, GLFS_LEASE_ID_SIZE); + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDWR, fd1, lid1); + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + /* reset counter */ + upcall_recv = 0; + + obj = glfs_h_lookupat(client2, NULL, TEST_FILE, NULL, 0); + ret = glfs_h_lease(client2, obj, &lease); + VERIFY_RESULT(2, ret, SHUD_FAIL); + + sleep(3); + /* should recv upcall */ + VERIFY_RESULT(6, !upcall_recv, SHUD_PASS); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = glfs_h_close(obj); + VERIFY_RESULT(3, ret, SHUD_PASS); + ret = glfs_close(fd1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + int i = 0; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd1 = NULL; + char *topdir = "topdir", *filename = "file1"; + char *buf = NULL; + int x = 0; + ssize_t xattr_size = -1; + + if (argc != 4) { + fprintf(stderr, + "Expect following args %s <Vol> <glfs client log file> " + "<testcase log file>\n", + argv[0]); + return -1; + } + + log_file = fopen(argv[3], "w"); + if (!log_file) + goto error; + + volname = argv[1]; + glfs_log_file = argv[2]; + + /* Setup 2 clients */ + client1 = setup_new_client(volname, glfs_log_file); + client2 = setup_new_client(volname, glfs_log_file); + + ret = testcase_recall_conflict_lease(); + VERIFY_RESULT(101, ret, SHUD_PASS); + + glfs_fini(client1); + glfs_fini(client2); + + fclose(log_file); + return 0; +error: + return -1; +} diff --git a/tests/features/glfs-lease.c b/tests/features/glfs-lease.c new file mode 100644 index 00000000000..e82cd875b38 --- /dev/null +++ b/tests/features/glfs-lease.c @@ -0,0 +1,717 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +/* Few rules: + * 1. A client may have multiple lease keys, but a lease key cannot be shared by + * multiple clients. + * 2. Lease key can be set before open, or in glfs_lease request. A lease key + * set like this is valid for the lifetime of the fd, i.e. a fd cannot have + * multiple lease key. But a lease key can be shared across multiple fds. + */ +glfs_t *client1 = NULL, *client2 = NULL, *client3 = NULL, *client4 = NULL; +glfs_fd_t *fd1 = NULL, *fd2 = NULL, *fd3 = NULL, *fd4 = NULL; +FILE *log_file = NULL; +char lid1[GLFS_LEASE_ID_SIZE] = "lid1-clnt1", + lid2[GLFS_LEASE_ID_SIZE] = "lid2-clnt2"; +char lid3[GLFS_LEASE_ID_SIZE] = "lid3-clnt2", lid4[GLFS_LEASE_ID_SIZE] = { + 0, +}; +char *volname = NULL, *glfs_log_file = NULL; + +#define MAX_CLIENTS 4 +#define MAX_FDS 4 +#define TEST_FILE "/test/lease" +#define SHUD_PASS 0 +#define SHUD_FAIL -1 +#define NONE 0 + +static void +recall_cbk(struct glfs_lease lease, void *data); + +static int +set_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, fd); + if (ret < 0) { + fprintf(log_file, "\n RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RD_LEASE"); + return ret; +} + +static int +set_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n RW_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Took RW_LEASE"); + return ret; +} + +static int +get_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_GET_LEASE; + lease.lease_type = -1; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n GET_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + if (lease.lease_type == GLFS_RD_LEASE) + fprintf(log_file, "\n Esisting Lease: RD_LEASE"); + else if (lease.lease_type == GLFS_RW_LEASE) + fprintf(log_file, "\n Esisting Lease: RW_LEASE"); + else if (lease.lease_type == 3) + fprintf(log_file, "\n Esisting Lease: RD_LEASE|RW_LEASE"); + else if (lease.lease_type == 0) + fprintf(log_file, "\n Esisting Lease: NONE"); + else + fprintf(log_file, "\n Existing lease type:%d", lease.lease_type); + return lease.lease_type; +} + +static int +unlk_write_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RW_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RW_LESAE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RW_LEASE"); + return ret; +} + +static int +unlk_read_lease(glfs_fd_t *fd, char ld[]) +{ + struct glfs_lease lease = { + 0, + }; + int ret = 0; + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_UNLK_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, ld, GLFS_LEASE_ID_SIZE); + + ret = glfs_lease(fd, &lease, &recall_cbk, NULL); + if (ret < 0) { + fprintf(log_file, "\n Unlock RD_LEASE failed with ret: %d (%s)", ret, + strerror(errno)); + return -1; + } + fprintf(log_file, "\n Unlocked RD_LEASE"); + return ret; +} + +glfs_t * +setup_new_client(char *volname, char *log_fileile) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new(volname); + if (!fs) { + fprintf(log_file, "\nglfs_new: returned NULL (%s)\n", strerror(errno)); + goto error; + } + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_volfile_server failed ret:%d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_set_logging(fs, log_fileile, 7); + if (ret < 0) { + fprintf(log_file, "\nglfs_set_logging failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + + ret = glfs_init(fs); + if (ret < 0) { + fprintf(log_file, "\nglfs_init failed with ret: %d (%s)\n", ret, + strerror(errno)); + goto error; + } + return fs; +error: + return NULL; +} + +#define OPEN(client, flags, fd, lease_id) \ + do { \ + int ret_val = 0; \ + ret_val = glfs_setfsleaseid(lease_id); \ + if (ret_val) { \ + fprintf(log_file, \ + "\nglfs_setfsleaseid failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + fd = glfs_open(client, TEST_FILE, flags); \ + if (fd == NULL) { \ + fprintf(log_file, "\nglfs_open failed with ret: %d (%s)\n", ret, \ + strerror(errno)); \ + return -1; \ + } \ + } while (0) + +#define VERIFY_RESULT(test_case, ret, value) \ + do { \ + if (ret != value) { \ + fprintf(log_file, \ + "\n Testcase %d failed, ret = %d, value=%d\n", \ + test_case, ret, value); \ + goto error; /*test unsuccessful*/ \ + } \ + fprintf(log_file, "\n Testcase %d Succeeded\n", test_case); \ + } while (0) + +static void +recall_cbk(struct glfs_lease lease, void *data) +{ + int ret = -1; + char ld[GLFS_LEASE_ID_SIZE] = ""; + + fprintf(log_file, "\nRECALL received on lease_id:(%s)", lease.lease_id); + memcpy(ld, lease.lease_id, GLFS_LEASE_ID_SIZE); + ret = unlk_write_lease((glfs_fd_t *)data, ld); + VERIFY_RESULT(500, ret, SHUD_PASS); +error: + return; +} + +static int +testcase1_rd_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Read lease:"); + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_FAIL); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_FAIL); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(7, ret, SHUD_PASS); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase2_wr_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Write lease:"); + /* Open fd on client 1 in WRonly mode */ + OPEN(client1, O_WRONLY, fd1, lid1); + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_FAIL); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(4, ret, GLFS_RW_LEASE); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(7, ret, SHUD_FAIL); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase3_rd_wr_lease() +{ + glfs_fd_t *fd1 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for Read Write lease:"); + /* Open fd on client 1 in WRonly mode */ + OPEN(client1, O_RDWR, fd1, lid1); + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, (GLFS_RW_LEASE | GLFS_RD_LEASE)); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(5, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase4_rd_lease_multi_clnt() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi client Read lease:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + + /* Open fd on client 2 in RW mode */ + OPEN(client2, O_RDONLY, fd2, lid2); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid2); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(6, ret, NONE); + + ret = get_lease(fd2, lid2); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(9, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase5_openfd_multi_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi lid openfd check:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDONLY, fd1, lid1); + + /* Open fd on client 2 in RW mode */ + OPEN(client2, O_RDWR, fd2, lid2); + OPEN(client2, O_RDWR, fd3, lid2); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT( + 1, ret, + SHUD_FAIL); /*As there are other openfds in WR mode from diff lid*/ + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT( + 2, ret, SHUD_FAIL); /*As thers is another fd in RD mode from diff lid */ + + ret = glfs_close(fd1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_write_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = glfs_close(fd3); + VERIFY_RESULT(7, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase6_openfd_same_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd3 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for same lid openfd check:"); + + /* Open fd on client 2 in RW mode */ + OPEN(client1, O_RDWR, fd1, lid2); + OPEN(client1, O_RDWR, fd2, lid2); + + ret = set_write_lease(fd1, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = set_write_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_write_lease(fd1, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = unlk_write_lease(fd2, lid2); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = glfs_close(fd1); + VERIFY_RESULT(6, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(7, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase7_rd_multi_lid() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for multi lease id Read lease:"); + + /* Open fd on client 1 in RD mode */ + OPEN(client2, O_RDONLY, fd1, lid2); + + /* Open fd on client 2 in RD mode */ + OPEN(client2, O_RDONLY, fd2, lid3); + + ret = set_read_lease(fd1, lid2); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = set_read_lease(fd2, lid3); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = get_lease(fd1, lid2); + VERIFY_RESULT(3, ret, GLFS_RD_LEASE); + + ret = unlk_read_lease(fd1, lid2); + VERIFY_RESULT(4, ret, SHUD_PASS); + + ret = unlk_read_lease(fd2, lid3); + VERIFY_RESULT(5, ret, SHUD_PASS); + + ret = get_lease(fd1, lid2); + VERIFY_RESULT(6, ret, NONE); + + ret = get_lease(fd2, lid3); + VERIFY_RESULT(7, ret, NONE); + + ret = glfs_close(fd1); + VERIFY_RESULT(8, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(9, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase8_client_disconnect() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for client disconnect cleanup"); + + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDWR, fd1, lid1); + + ret = set_read_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(2, ret, GLFS_RD_LEASE); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(3, ret, SHUD_PASS); + + ret = get_lease(fd1, lid1); + VERIFY_RESULT(4, ret, (GLFS_RD_LEASE | GLFS_RW_LEASE)); + + ret = glfs_fini(client1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + /* Open fd on client 2 in RD mode */ + OPEN(client2, O_RDONLY, fd2, lid3); + + ret = get_lease(fd2, lid3); + VERIFY_RESULT(6, ret, NONE); + + ret = glfs_close(fd2); + VERIFY_RESULT(7, ret, SHUD_PASS); + + client1 = setup_new_client(volname, glfs_log_file); + + return 0; +error: + return -1; +} + +static int +testcase9_recall_conflict_lease() +{ + struct glfs_object *obj = NULL; + glfs_fd_t *fd1 = NULL; + int ret = 0; + struct glfs_lease lease = { + 0, + }; + + fprintf(log_file, + "\n Basic test case for conflicting lease causing recall"); + + memset(&lease, 0, sizeof(lease)); + lease.cmd = GLFS_SET_LEASE; + lease.lease_type = GLFS_RD_LEASE; + memcpy(&lease.lease_id, lid2, GLFS_LEASE_ID_SIZE); + /* Open fd on client 1 in RD mode */ + OPEN(client1, O_RDWR, fd1, lid1); + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + obj = glfs_h_lookupat(client2, NULL, TEST_FILE, NULL, 0); + ret = glfs_h_lease(client2, obj, &lease); + VERIFY_RESULT(2, ret, SHUD_FAIL); + + ret = unlk_write_lease(fd1, lid1); + VERIFY_RESULT(5, ret, SHUD_PASS); + + sleep(3); + ret = glfs_h_close(obj); + VERIFY_RESULT(3, ret, SHUD_PASS); + ret = glfs_close(fd1); + VERIFY_RESULT(4, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +static int +testcase10_recall_open_conflict() +{ + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + int ret = 0; + + fprintf(log_file, "\n Basic test case for conflicting open causing recall"); + + /* Open fd on client 1 in RW mode */ + OPEN(client1, O_RDWR, fd1, lid1); + + ret = set_write_lease(fd1, lid1); + VERIFY_RESULT(1, ret, SHUD_PASS); + + /* Open fd on client 1 in RW mode */ + OPEN(client2, O_RDWR, fd2, lid2); + + /* TODO: Check for recall cbk functionality */ + ret = glfs_close(fd1); + VERIFY_RESULT(2, ret, SHUD_PASS); + + ret = glfs_close(fd2); + VERIFY_RESULT(3, ret, SHUD_PASS); + + return 0; +error: + return -1; +} + +int +main(int argc, char *argv[]) +{ + int ret = 0; + int i = 0; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd1 = NULL; + char *topdir = "topdir", *filename = "file1"; + char *buf = NULL; + int x = 0; + ssize_t xattr_size = -1; + + if (argc != 4) { + fprintf(stderr, + "Expect following args %s <Vol> <glfs client log file> " + "<testcase log file>\n", + argv[0]); + return -1; + } + + log_file = fopen(argv[3], "w"); + if (!log_file) + goto error; + + volname = argv[1]; + glfs_log_file = argv[2]; + + /* Setup 3 clients */ + client1 = setup_new_client(volname, glfs_log_file); + client2 = setup_new_client(volname, glfs_log_file); + client3 = setup_new_client(volname, glfs_log_file); + + ret = testcase1_rd_lease(); + VERIFY_RESULT(101, ret, SHUD_PASS); + + ret = testcase2_wr_lease(); + VERIFY_RESULT(102, ret, SHUD_PASS); + + ret = testcase3_rd_wr_lease(); + VERIFY_RESULT(103, ret, SHUD_PASS); + + ret = testcase4_rd_lease_multi_clnt(); + VERIFY_RESULT(104, ret, SHUD_PASS); + + ret = testcase5_openfd_multi_lid(); + VERIFY_RESULT(105, ret, SHUD_PASS); + + ret = testcase6_openfd_same_lid(); + VERIFY_RESULT(106, ret, SHUD_PASS); + + ret = testcase7_rd_multi_lid(); + VERIFY_RESULT(107, ret, SHUD_PASS); + + ret = testcase8_client_disconnect(); + VERIFY_RESULT(108, ret, SHUD_PASS); + + ret = testcase9_recall_conflict_lease(); + VERIFY_RESULT(109, ret, SHUD_PASS); + + ret = testcase10_recall_open_conflict(); + VERIFY_RESULT(110, ret, SHUD_PASS); + + glfs_fini(client1); + glfs_fini(client2); + glfs_fini(client3); + + fclose(log_file); + return 0; +error: + return -1; +} diff --git a/tests/features/glfs-lease.t b/tests/features/glfs-lease.t new file mode 100755 index 00000000000..6ef6da05043 --- /dev/null +++ b/tests/features/glfs-lease.t @@ -0,0 +1,31 @@ +#!/bin/bash +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +## Start and create a volume +TEST glusterd; +TEST pidof glusterd; +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/${V0}; +TEST $CLI volume set $V0 leases on +TEST $CLI volume set $V0 open-behind off +TEST $CLI volume set $V0 write-behind on +TEST $CLI volume start $V0 + +logdir=`gluster --print-logdir` +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +TEST mkdir $M0/test +TEST touch $M0/test/lease + +build_tester $(dirname $0)/glfs-lease.c -lgfapi +build_tester $(dirname $0)/glfs-lease-recall.c -lgfapi +TEST $(dirname $0)/glfs-lease $V0 $logdir/glfs-lease.log $logdir/lease-test.log +TEST $(dirname $0)/glfs-lease-recall $V0 $logdir/glfs-lease-recall.log $logdir/lease-test-recall.log + +TEST $CLI volume set $V0 leases off + +cleanup_tester $(dirname $0)/glfs-lease +cleanup; diff --git a/tests/features/glupy.t b/tests/features/glupy.t deleted file mode 100755 index faa4cf33a14..00000000000 --- a/tests/features/glupy.t +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -. $(dirname $0)/../include.rc -. $(dirname $0)/../volume.rc - -echo $PYTHON_PATH >&2 -cleanup; - -TEST mkdir -p $B0/glupytest -cat > $B0/glupytest.vol <<EOF -volume vol-posix - type storage/posix - option directory $B0/glupytest -end-volume - -volume vol-glupy - type features/glupy - option module-name helloworld - subvolumes vol-posix -end-volume -EOF - -TEST glusterfs -f $B0/glupytest.vol -l $LOGDIR/glupy.log $M0; - -TEST touch $M0/filename; -EXPECT "filename" ls $M0 -TEST rm -f $M0/filename; - -EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0; - -cleanup; diff --git a/tests/features/interrupt.t b/tests/features/interrupt.t new file mode 100644 index 00000000000..067eb1b7486 --- /dev/null +++ b/tests/features/interrupt.t @@ -0,0 +1,71 @@ +#!/bin/bash + +##Copy this file to tests/bugs before running run.sh (cp extras/test/bug-920583.t tests/bugs/) + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +TESTS_EXPECTED_IN_LOOP=4 + +cleanup; +logdir=`gluster --print-logdir` + +TEST build_tester $(dirname $0)/open_and_sleep.c + +## Start and create a volume +TEST glusterd; +TEST pidof glusterd; + +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1,2,3,4,5,6,7,8,9}; + +## Verify volume is is created +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +## Start volume and verify +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +function log-file-name() +{ + logfilename=$M0".log" + echo ${logfilename:1} | tr / - +} + +log_file=$logdir"/"`log-file-name` + +function test_interrupt { + local handlebool="$1" + local logpattern="$2" + + TEST $GFS --volfile-id=$V0 --volfile-server=$H0 --fuse-flush-handle-interrupt=$handlebool --log-level=DEBUG $M0 + + # If the test helper fails (which is considered a setup error, not failure of the test + # case itself), kill will be invoked without argument, and that will be the actual + # error which is caught. + TEST "./$(dirname $0)/open_and_sleep $M0/testfile-$handlebool | { sleep 0.1; xargs -n1 kill -INT; }" + + TEST "grep -E '$logpattern' $log_file" + # Basic sanity check, making sure filesystem has not crashed. + TEST test -f $M0/testfile-$handlebool +} + +# Theoretically FLUSH might finish before INTERRUPT is handled, +# in which case we'd get the "no handler found" message instead of +# "interrupt handler triggered" (but it's unlikely). +# If that's observed, the pattern can be changed to +# 'FLUSH.*interrupt handler triggered|[I]NTERRUPT.*no handler found' +# to fix the test. +test_interrupt yes '[F]LUSH.*interrupt handler triggered' +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +test_interrupt no '[I]NTERRUPT.*no handler found' + +## Finish up +TEST $CLI volume stop $V0; +EXPECT 'Stopped' volinfo_field $V0 'Status'; + +TEST $CLI volume delete $V0; +TEST ! $CLI volume info $V0; + +cleanup_tester $(dirname $0)/open_and_sleep; +cleanup; diff --git a/tests/features/ipc.t b/tests/features/ipc.t index 55ce8c871c1..5c92287eaa1 100755 --- a/tests/features/ipc.t +++ b/tests/features/ipc.t @@ -2,6 +2,9 @@ . $(dirname $0)/../include.rc +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=GH269 +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=GH269 + cleanup; mkdir -p $B0/1 mkdir -p $M0 diff --git a/tests/features/ipctest.py b/tests/features/ipctest.py index 857225fe0a5..f6f699cf5c4 100755 --- a/tests/features/ipctest.py +++ b/tests/features/ipctest.py @@ -1,25 +1,19 @@ -#!/usr/bin/python +from __future__ import print_function import ctypes -import ctypes.util -# find_library does not lookup LD_LIBRARY_PATH and may miss the -# function. In that case, retry with less portable but explicit name. -libgfapi = ctypes.util.find_library("gfapi") -if libgfapi == None: - libgfapi = "libgfapi.so" -api = ctypes.CDLL(libgfapi,mode=ctypes.RTLD_GLOBAL) +api = ctypes.CDLL("libgfapi.so", mode=ctypes.RTLD_GLOBAL) -api.glfs_ipc.argtypes = [ ctypes.c_void_p, ctypes.c_int ] +api.glfs_ipc.argtypes = [ ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p ] api.glfs_ipc.restype = ctypes.c_int def do_ipc (host, volume): fs = api.glfs_new(volume) - #api.glfs_set_logging(fs,"/dev/stderr",7) - api.glfs_set_volfile_server(fs,"tcp",host,24007) + #api.glfs_set_logging(fs, "/dev/stderr", 7) + api.glfs_set_volfile_server(fs, "tcp", host, 24007) api.glfs_init(fs) - ret = api.glfs_ipc(fs,1470369258) + ret = api.glfs_ipc(fs, 1470369258, 0, 0) api.glfs_fini(fs) return ret @@ -28,7 +22,7 @@ if __name__ == "__main__": import sys try: - res = apply(do_ipc,sys.argv[1:3]) - print res + res = do_ipc(*sys.argv[1:3]) + print(res) except: - print "IPC failed (volume not started?)" + print("IPC failed (volume not started?)") diff --git a/tests/features/leases.t b/tests/features/leases.t deleted file mode 100755 index 27f0405cfb1..00000000000 --- a/tests/features/leases.t +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -. $(dirname $0)/../include.rc -. $(dirname $0)/../volume.rc - -cleanup; - -## Start and create a volume -TEST glusterd; -TEST pidof glusterd; -TEST $CLI volume info; - -TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2}; -TEST $CLI volume start $V0 -TEST $CLI volume set $V0 leases on - -TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; -TEST mkdir $M0/test -TEST touch $M0/test/lease - -TEST $CLI volume set $V0 leases off - -cleanup; diff --git a/tests/features/lock-migration/lkmigration-set-option.t b/tests/features/lock-migration/lkmigration-set-option.t deleted file mode 100644 index 4340438591f..00000000000 --- a/tests/features/lock-migration/lkmigration-set-option.t +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Test to check -. $(dirname $0)/../../include.rc -. $(dirname $0)/../../volume.rc - -#Check lock-migration set option sanity -cleanup; - -TEST glusterd -TEST pidof glusterd -TEST $CLI volume create $V0 $H0:$B0/brick1 $H0:$B0/brick2 -TEST $CLI volume start $V0 - -TEST $CLI volume set $V0 lock-migration on -EXPECT "on" echo `$CLI volume info | grep lock-migration | awk '{print $2}'` -TEST $CLI volume set $V0 lock-migration off -EXPECT "off" echo `$CLI volume info | grep lock-migration | awk '{print $2}'` -TEST ! $CLI volume set $V0 lock-migration garbage -#make sure it is still off -EXPECT "off" echo `$CLI volume info | grep lock-migration | awk '{print $2}'` - - -TEST $CLI volume stop $V0; -TEST $CLI volume delete $V0; - - -#create a afr volume and make sure option setting fails - -TEST $CLI volume create $V0 replica 2 $H0:$B0/brick1 $H0:$B0/brick2 -TEST $CLI volume start $V0 - -TEST ! $CLI volume set $V0 lock-migration on - -cleanup; diff --git a/tests/features/lock_revocation.t b/tests/features/lock_revocation.t new file mode 100644 index 00000000000..67bc13159f9 --- /dev/null +++ b/tests/features/lock_revocation.t @@ -0,0 +1,54 @@ +#!/bin/bash +logdir=$(gluster --print-logdir) +BRICK_LOGFILES="$logdir/bricks/d-backends-brick?.log" +rm -f $BRICK_LOGFILES &> /dev/null + +# Test that lock revocation works + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +cleanup; + +function deadlock_fop() { + local MNT=$1 + for i in {1..1000}; do + dd if=/dev/zero of=$MNT/testfile bs=1k count=10 &> /dev/null + if grep "MONKEY LOCKING" $BRICK_LOGFILES &> /dev/null; then + break + fi + done +} + +function monkey_unlock() { + grep "MONKEY LOCKING" $BRICK_LOGFILES &> /dev/null && echo SUCCESS + return 0 +} + +function append_to_file() { + local FILE_PATH=$1 + echo "hello" >> $FILE_PATH + return 0 +} + +#Init +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1} +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 features.locks-monkey-unlocking on +TEST $CLI volume set $V0 features.locks-revocation-secs 2 +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=$V0 -s $H0 $M0; +TEST $GFS --volfile-id=$V0 -s $H0 $M1; + +# Deadlock writes to a file using monkey unlocking +deadlock_fop $M0 & +EXPECT_WITHIN 60 "SUCCESS" monkey_unlock + +# Sleep > unlock timeout and attempt to write to the file +sleep 3 +TEST append_to_file $M1/testfile + +cleanup +#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1369401 +#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1448364 diff --git a/tests/features/mandatory-lock-forced.c b/tests/features/mandatory-lock-forced.c index f37206845f1..4028d6c6eaf 100644 --- a/tests/features/mandatory-lock-forced.c +++ b/tests/features/mandatory-lock-forced.c @@ -6,133 +6,138 @@ #include <string.h> #include <sys/wait.h> -#define LOG_ERR(func, err) do { \ - fprintf (stderr, "%s : returned error (%s)\n", func, strerror(err)); \ - exit (err); \ -} while (0) - -int fd; -struct flock lock; -char *buf = "ten bytes!"; -char *fname = "/mnt/glusterfs/0/mand.lock"; -int open_flags, child, err, status, blocked = 0; - -int do_child (char *argv[]) { - /* Initialize file open flags */ - if (strcmp (argv[2], "BLOCK") == 0) - open_flags = O_RDWR; - else if (strcmp (argv[2], "TRUNC") == 0) - open_flags = O_RDWR | O_TRUNC | O_NONBLOCK; - else if (strcmp (argv[2], "NONE") == 0) - open_flags = O_RDWR | O_NONBLOCK; - else - LOG_ERR ("Invalid option:", EINVAL); - - /* Open the file */ - fd = open (fname, open_flags); - if (fd == -1) - LOG_ERR ("Child open", errno); - - /* Perform the file operation*/ - if (strcmp (argv[3], "READ") == 0) { - buf = NULL; - err = read (fd, buf, 10); - if (err == -1) - LOG_ERR ("Child read", errno); - } else if (strcmp (argv[3], "WRITE") == 0) { - err = write (fd, buf, 10); - if (err == -1) - LOG_ERR ("Child write", errno); - } else if (strcmp (argv[3], "FTRUNCATE") == 0) { - err = ftruncate (fd, 5); - if (err) - LOG_ERR ("Child ftruncate", errno); - } else - LOG_ERR ("Invalid operation:", EINVAL); - - /* Close child fd */ - err = close (fd); +#define LOG_ERR(func, err) \ + do { \ + fprintf(stderr, "%s : returned error (%s)\n", func, strerror(err)); \ + exit(err); \ + } while (0) + +int fd; +struct flock lock; +char *buf = "ten bytes!"; +char *fname = "/mnt/glusterfs/0/mand.lock"; +int open_flags, child, err, status, blocked = 0; + +int +do_child(char *argv[]) +{ + /* Initialize file open flags */ + if (strcmp(argv[2], "BLOCK") == 0) + open_flags = O_RDWR; + else if (strcmp(argv[2], "TRUNC") == 0) + open_flags = O_RDWR | O_TRUNC | O_NONBLOCK; + else if (strcmp(argv[2], "NONE") == 0) + open_flags = O_RDWR | O_NONBLOCK; + else + LOG_ERR("Invalid option:", EINVAL); + + /* Open the file */ + fd = open(fname, open_flags); + if (fd == -1) + LOG_ERR("Child open", errno); + + /* Perform the file operation*/ + if (strcmp(argv[3], "READ") == 0) { + buf = NULL; + err = read(fd, buf, 10); + if (err == -1) + LOG_ERR("Child read", errno); + } else if (strcmp(argv[3], "WRITE") == 0) { + err = write(fd, buf, 10); + if (err == -1) + LOG_ERR("Child write", errno); + } else if (strcmp(argv[3], "FTRUNCATE") == 0) { + err = ftruncate(fd, 5); if (err) - LOG_ERR ("Child close", errno); + LOG_ERR("Child ftruncate", errno); + } else + LOG_ERR("Invalid operation:", EINVAL); - /* Exit success */ - exit (0); + /* Close child fd */ + err = close(fd); + if (err) + LOG_ERR("Child close", errno); + + /* Exit success */ + exit(0); } -int main (int argc, char *argv[]) { - if (argc < 4) { - fprintf (stderr, "Wrong usage: Use as ./mandatory-lock " - "<RD_LCK/WR_LCK> <BLOCK/TRUNC/NONE> " - "<READ/WRITE/FTRUNCATE\n"); - exit(EINVAL); +int +main(int argc, char *argv[]) +{ + if (argc < 4) { + fprintf(stderr, + "Wrong usage: Use as ./mandatory-lock " + "<RD_LCK/WR_LCK> <BLOCK/TRUNC/NONE> " + "<READ/WRITE/FTRUNCATE\n"); + exit(EINVAL); + } + /* Create an empty lock file */ + fd = open(fname, O_CREAT | O_RDWR, 0755); + if (fd == -1) + LOG_ERR("Parent create", errno); + + /* Determine the type of lock */ + if (strcmp(argv[1], "RD_LCK") == 0) + lock.l_type = F_RDLCK; + else if (strcmp(argv[1], "WR_LCK") == 0) + lock.l_type = F_WRLCK; + else + LOG_ERR("Parent lock type", EINVAL); + + lock.l_whence = SEEK_SET; + lock.l_start = 0L; + lock.l_len = 0L; + + /* Let parent acquire the initial lock */ + err = fcntl(fd, F_SETLK, &lock); + if (err) + LOG_ERR("Parent lock", errno); + + /* Now fork a child */ + child = fork(); + if (child == 0) + /* Perform the child operations */ + do_child(argv); + else { + /* If blocking mode, then sleep for 2 seconds + * and wait for the child */ + if (strcmp(argv[2], "NONE") != 0) { + sleep(2); + if (waitpid(child, &status, WNOHANG) == 0) + blocked = 1; + /* Release the parent lock so that the + * child can terminate */ + lock.l_type = F_UNLCK; + err = fcntl(fd, F_SETLK, &lock); + if (err) + LOG_ERR("Parent unlock", errno); } - /* Create an empty lock file */ - fd = open (fname, O_CREAT | O_RDWR, 0755); - if (fd == -1) - LOG_ERR ("Parent create", errno); - - /* Determine the type of lock */ - if (strcmp (argv[1], "RD_LCK") == 0) - lock.l_type = F_RDLCK; - else if (strcmp (argv[1], "WR_LCK") == 0) - lock.l_type = F_WRLCK; - else - LOG_ERR ("Parent lock type", EINVAL); - - lock.l_whence = SEEK_SET; - lock.l_start = 0L; - lock.l_len = 0L; - - /* Let parent acquire the initial lock */ - err = fcntl (fd, F_SETLK, &lock); + + /* Wait for child to finish */ + waitpid(child, &status, 0); + + /* Close the parent fd */ + err = close(fd); if (err) - LOG_ERR ("Parent lock", errno); - - /* Now fork a child */ - child = fork (); - if (child == 0) - /* Perform the child operations */ - do_child (argv); - else { - /* If blocking mode, then sleep for 2 seconds - * and wait for the child */ - if (strcmp (argv[2], "NONE") != 0) { - sleep (2); - if (waitpid (child, &status, WNOHANG) == 0) - blocked = 1; - /* Release the parent lock so that the - * child can terminate */ - lock.l_type = F_UNLCK; - err = fcntl (fd, F_SETLK, &lock); - if (err) - LOG_ERR ("Parent unlock", errno); - } - - /* Wait for child to finish */ - waitpid (child, &status, 0); - - /* Close the parent fd */ - err = close (fd); - if (err) - LOG_ERR ("Parent close", errno); - - /* Remove the lock file*/ - err = unlink (fname); - if (err) - LOG_ERR ("Parent unlink", errno); - - /* If not blocked, exit with child exit status*/ - errno = WEXITSTATUS(status); - - /* If blocked, exit with corresponding - * error code */ - if (blocked) - errno = EWOULDBLOCK; - - if (errno != 0) - printf ("%s\n", strerror(errno)); - - exit (errno); + LOG_ERR("Parent close", errno); - } + /* Remove the lock file*/ + err = unlink(fname); + if (err) + LOG_ERR("Parent unlink", errno); + + /* If not blocked, exit with child exit status*/ + errno = WEXITSTATUS(status); + + /* If blocked, exit with corresponding + * error code */ + if (blocked) + errno = EWOULDBLOCK; + + if (errno != 0) + printf("%s\n", strerror(errno)); + + exit(errno); + } } diff --git a/tests/features/nuke.t b/tests/features/nuke.t index ace847bc99b..f1f5f9f90ab 100755 --- a/tests/features/nuke.t +++ b/tests/features/nuke.t @@ -20,7 +20,7 @@ LANDFILL=$B0/${V0}1/.glusterfs/landfill TEST glusterd -TEST $CLI volume create $V0 $H0:$B0/${V0}1 +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2} TEST $CLI volume start $V0 TEST $GFS -s $H0 --volfile-id $V0 $M0 diff --git a/tests/features/open_and_sleep.c b/tests/features/open_and_sleep.c new file mode 100644 index 00000000000..7d0e22a2503 --- /dev/null +++ b/tests/features/open_and_sleep.c @@ -0,0 +1,27 @@ +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> + +int +main(int argc, char **argv) +{ + pid_t pid; + int fd; + + if (argc >= 2) { + fd = open(argv[1], O_RDWR | O_CREAT, 0644); + if (fd == -1) { + fprintf(stderr, "cannot open/create %s\n", argv[1]); + return 1; + } + } + + pid = getpid(); + printf("%d\n", pid); + fflush(stdout); + + for (;;) + sleep(1); + + return 0; +} diff --git a/tests/features/recon.t b/tests/features/recon.t new file mode 100644 index 00000000000..82ef6fd755d --- /dev/null +++ b/tests/features/recon.t @@ -0,0 +1,59 @@ +#!/bin/bash + +. $(dirname $0)/../traps.rc +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../fdl.rc + +tmpdir=$(mktemp -d -t ${0##*/}.XXXXXX) +push_trapfunc "rm -rf $tmpdir" + +write_file () { + echo "peekaboo" > $1 +} + +TEST rm -f $FDL_META_FILE $FDL_DATA_FILE +TEST glusterd +TEST pidof glusterd + +# Get a simple volume set up and mounted with FDL active. +TEST $CLI volume create $V0 ${H0}:${B0}/${V0}-0 +TEST $CLI volume set $V0 features.fdl on +TEST $CLI volume start $V0 +TEST $GFS -s $H0 --volfile-id $V0 $M0 + +# Generate some I/O and then copy off the journal files for later. +TEST mkdir -p $M0/abc/def +TEST write_file $M0/abc/def/ghi +#EST chmod 314 $M0/abc/def/ghi +cp ${FDL_META_FILE} ${FDL_DATA_FILE} ${tmpdir} + +# Get back to an empty state and unmount. +TEST rm -rf $M0/abc +TEST umount $M0 + +# Make sure we really are in an empty state. Otherwise the tests below could +# pass just because we never cleaned up in the first place. +TEST [ ! -d ${B0}/${V0}-0/abc ] + +# Create a stub volfile. +vol_file=${GLUSTERD_WORKDIR}/vols/${V0}/${V0}.${H0}.${log_id}.vol +vol_id_line=$(grep volume-id ${vol_file}) +cat > ${tmpdir}/recon.vol << EOF +volume recon-posix + type storage/posix + option directory ${B0}/${V0}-0 +${vol_id_line} +end-volume +EOF + +TEST gf_recon ${tmpdir}/recon.vol ${tmpdir}/$(basename ${FDL_META_FILE}) \ + ${tmpdir}/$(basename ${FDL_DATA_FILE}) + +TEST [ -d ${B0}/${V0}-0/abc/def ] +EXPECT "peekaboo" cat ${B0}/${V0}-0/abc/def/ghi +# TBD: test permissions, xattrs + +cleanup +#G_TESTDEF_TEST_STATUS_CENTOS6=KNOWN_ISSUE,BUG=1385758 +#G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=1385758 diff --git a/tests/features/ssl-authz.t b/tests/features/ssl-authz.t index 3cb45b5e582..497083e5a3a 100755 --- a/tests/features/ssl-authz.t +++ b/tests/features/ssl-authz.t @@ -25,6 +25,7 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume info; +TEST $CLI v set all cluster.brick-multiplex on # Construct a cipher list that excludes CBC because of POODLE. # http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3566 # @@ -41,16 +42,16 @@ function valid_ciphers { -e '/:$/s///' } -TEST openssl genrsa -out $SSL_KEY 1024 +TEST openssl genrsa -out $SSL_KEY 2048 TEST openssl req -new -x509 -key $SSL_KEY -subj /CN=Anyone -out $SSL_CERT ln $SSL_CERT $SSL_CA -TEST $CLI volume create $V0 $H0:$B0/1 +TEST $CLI volume create $V0 replica 3 $H0:$B0/{1,2,3} force TEST $CLI volume set $V0 server.ssl on TEST $CLI volume set $V0 client.ssl on TEST $CLI volume set $V0 ssl.cipher-list $(valid_ciphers) TEST $CLI volume start $V0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" online_brick_count # This mount should SUCCEED because ssl-allow=* by default. This effectively # disables SSL authorization, though authentication and encryption might still @@ -59,11 +60,28 @@ TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0 TEST ping_file $M0/before EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 +glusterfsd_pid=`pgrep glusterfsd` +TEST [ $glusterfsd_pid != 0 ] +start=`pmap -x $glusterfsd_pid | grep total | awk -F " " '{print $4}'` +echo "Memory consumption for glusterfsd process" +for i in $(seq 1 100); do + gluster v heal $V0 info >/dev/null +done +#Wait to cleanup memory +sleep 10 +end=`pmap -x $glusterfsd_pid | grep total | awk -F " " '{print $4}'` +diff=$((end-start)) + +# If memory consumption is more than 15M some leak in SSL code path + +TEST [ $diff -lt 15000 ] + + # Set ssl-allow to a wildcard that includes our identity. TEST $CLI volume stop $V0 TEST $CLI volume set $V0 auth.ssl-allow Any* TEST $CLI volume start $V0 -EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" online_brick_count # This mount should SUCCEED because we match the wildcard. TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0 diff --git a/tests/features/ssl-ciphers.t b/tests/features/ssl-ciphers.t index f5909f320ac..b70fe360e02 100644 --- a/tests/features/ssl-ciphers.t +++ b/tests/features/ssl-ciphers.t @@ -4,11 +4,7 @@ . $(dirname $0)/../volume.rc brick_port() { - $CLI volume status $1 | awk ' - ($3 == "") { p = $0; next; } - { $0 = p $0; p = ""; } - /^Brick/ { print $3; } - ' + $CLI --xml volume status $1 | sed -n '/.*<port>\([0-9]*\).*/s//\1/p' } wait_mount() { @@ -37,16 +33,26 @@ wait_mount() { openssl_connect() { ssl_opt="-verify 3 -verify_return_error -CAfile $SSL_CA" ssl_opt="$ssl_opt -crl_check_all -CApath $TMPDIR" - CIPHER=`echo "" | - openssl s_client $ssl_opt $@ 2>/dev/null | - awk '/^ Cipher/{print $3}'` - if [ "x${CIPHER}" = "x" -o "x${CIPHER}" = "x0000" ] ; then + cmd="echo "" | openssl s_client $ssl_opt $@ 2>/dev/null" + CIPHER=$(eval $cmd | awk -F "Cipher is" '{print $2}' | tr -d '[:space:]' | awk -F " " '{print $1}') + if [ "x${CIPHER}" = "x" -o "x${CIPHER}" = "x0000" -o "x${CIPHER}" = "x(NONE)" ] ; then echo "N" else echo "Y" fi } +#Validate the cipher to pass EXPECT test case before call openssl_connect +check_cipher() { + cmd="echo "" | openssl s_client $@ 2> /dev/null" + cipher=$(eval $cmd |awk -F "Cipher is" '{print $2}' | tr -d '[:space:]' | awk -F " " '{print $1}') + if [ "x${cipher}" = "x" -o "x${cipher}" = "x0000" -o "x${cipher}" = "x(NONE)" ] ; then + echo "N" + else + echo "Y" + fi +} + cleanup; mkdir -p $B0 mkdir -p $M0 @@ -67,7 +73,7 @@ TEST glusterd TEST pidof glusterd TEST $CLI volume info; -TEST openssl genrsa -out $SSL_KEY 1024 2>/dev/null +TEST openssl genrsa -out $SSL_KEY 2048 2>/dev/null TEST openssl req -config $SSL_CFG -new -key $SSL_KEY -x509 \ -subj /CN=CA -out $SSL_CA TEST openssl req -config $SSL_CFG -new -key $SSL_KEY \ @@ -104,32 +110,47 @@ EXPECT "N" openssl_connect -ssl2 -connect $H0:$BRICK_PORT # Test SSLv3 protocol fails EXPECT "N" openssl_connect -ssl3 -connect $H0:$BRICK_PORT -# Test TLSv1 protocol fails -EXPECT "N" openssl_connect -tls1 -connect $H0:$BRICK_PORT +# Test TLSv1 protocol based on openssl version +cmd="openssl version" +ver=$(eval $cmd | awk -F " " '{print $2}' | grep "^1.1") +if [ "x${ver}" = "x" ]; then + supp="N" +else + supp="Y" +fi +EXPECT "${supp}" openssl_connect -tls1 -connect $H0:$BRICK_PORT # Test a HIGH CBC cipher -EXPECT "Y" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES256-SHA -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT # Test EECDH -EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher EECDH -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT # test MD5 fails -EXPECT "N" openssl_connect -cipher DES-CBC3-MD5 -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher DES-CBC3-MD5 -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher DES-CBC3-MD5 -connect $H0:$BRICK_PORT # test RC4 fails -EXPECT "N" openssl_connect -cipher RC4-SHA -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher RC4-SHA -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher RC4-SHA -connect $H0:$BRICK_PORT # test eNULL fails -EXPECT "N" openssl_connect -cipher NULL-SHA256 -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher NULL-SHA256 -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher NULL-SHA256 -connect $H0:$BRICK_PORT # test SHA2 -EXPECT "Y" openssl_connect -cipher AES256-SHA256 -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES256-SHA256 -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES256-SHA256 -connect $H0:$BRICK_PORT # test GCM -EXPECT "Y" openssl_connect -cipher AES256-GCM-SHA384 -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES256-GCM-SHA384 -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES256-GCM-SHA384 -connect $H0:$BRICK_PORT # Test DH fails without DH params -EXPECT "N" openssl_connect -cipher EDH -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher EDH -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher EDH -connect $H0:$BRICK_PORT # Test DH with DH params TEST $CLI volume set $V0 ssl.dh-param `pwd`/`dirname $0`/dh1024.pem @@ -147,8 +168,10 @@ TEST $CLI volume stop $V0 TEST $CLI volume start $V0 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count BRICK_PORT=`brick_port $V0` -EXPECT "Y" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT -EXPECT "N" openssl_connect -cipher AES128-SHA -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES256-SHA -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES128-SHA -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES128-SHA -connect $H0:$BRICK_PORT # Test the ec-curve option TEST $CLI volume set $V0 ssl.cipher-list EECDH:EDH:!TLSv1 @@ -157,8 +180,10 @@ TEST $CLI volume stop $V0 TEST $CLI volume start $V0 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count BRICK_PORT=`brick_port $V0` -EXPECT "N" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT -EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher AES256-SHA -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher EECDH -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT TEST $CLI volume set $V0 ssl.ec-curve invalid EXPECT invalid volume_option $V0 ssl.ec-curve @@ -166,7 +191,8 @@ TEST $CLI volume stop $V0 TEST $CLI volume start $V0 EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count BRICK_PORT=`brick_port $V0` -EXPECT "N" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT +cph=`check_cipher -cipher EECDH -connect $H0:$BRICK_PORT` +EXPECT "$cph" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT TEST $CLI volume set $V0 ssl.ec-curve secp521r1 EXPECT secp521r1 volume_option $V0 ssl.ec-curve @@ -177,8 +203,6 @@ BRICK_PORT=`brick_port $V0` EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT # test revocation -# no need to restart the volume since the options are used -# by the client here. TEST $CLI volume set $V0 ssl.crl-path $TMPDIR EXPECT $TMPDIR volume_option $V0 ssl.crl-path $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 @@ -191,14 +215,25 @@ TEST openssl ca -batch -config $SSL_CFG -revoke $SSL_CERT 2>&1 TEST openssl ca -config $SSL_CFG -gencrl -out $SSL_CRL 2>&1 # Failed once revoked +# Although client fails to mount without restarting the server after crl-path +# is set when no actual crl file is found on the client, it would also fail +# when server is restarted for the same reason. Since the socket initialization +# code is the same for client and server, the crl verification flags need to +# be turned off for the client to avoid SSL searching for CRLs in the +# ssl.crl-path. If no CRL files are found in the ssl.crl-path, SSL fails the +# connect() attempt on the client. +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 EXPECT "N" wait_mount $M0 TEST ! test -f $TEST_FILE EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 # Succeed with CRL disabled +TEST $CLI volume stop $V0 TEST $CLI volume set $V0 ssl.crl-path NULL EXPECT NULL volume_option $V0 ssl.crl-path +TEST $CLI volume start $V0 $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 EXPECT "Y" wait_mount $M0 TEST test -f $TEST_FILE diff --git a/tests/features/subdir-mount.t b/tests/features/subdir-mount.t new file mode 100644 index 00000000000..a02bd6befc4 --- /dev/null +++ b/tests/features/subdir-mount.t @@ -0,0 +1,121 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../nfs.rc + +cleanup; + +## Start and create a volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4}; + +## Start volume and verify +TEST $CLI volume start $V0; + +## Mount FUSE with caching disabled (read-write) +TEST $GFS -s $H0 --volfile-id $V0 --volume-name ${V0}-dht $M0; + +TEST ! stat $M0/subdir1; +TEST mkdir $M0/subdir1; +TEST ! stat $M0/subdir2; +TEST mkdir $M0/subdir2; +TEST ! stat $M0/subdir1/subdir1.1; +TEST mkdir $M0/subdir1/subdir1.1; +TEST ! stat $M0/subdir1/subdir1.1/subdir1.2; +TEST mkdir $M0/subdir1/subdir1.1/subdir1.2; + +# mount volume/subdir1 +TEST $GFS --subdir-mount /subdir1 -s $H0 --volfile-id $V0 --volume-name ${V0}-dht $M1; + +TEST touch $M0/topfile; +TEST ! stat $M1/topfile; + +TEST touch $M1/subdir1_file; +TEST ! stat $M0/subdir1_file; +TEST stat $M0/subdir1/subdir1_file; + +# mount volume/subdir2 +TEST $GFS --subdir-mount /subdir2 -s $H0 --volfile-id $V0 $M2; + +TEST ! stat $M2/topfile; + +TEST touch $M2/subdir2_file; +TEST ! stat $M0/subdir2_file; +TEST ! stat $M1/subdir2_file; +TEST stat $M0/subdir2/subdir2_file; + +# umount $M1 / $M2 +TEST umount $M1 +TEST umount $M2 + +# mount non-existing subdir ; this works with mount.glusterfs, +# but with glusterfs, the script doesn't returns error. +#TEST ! $GFS --subdir-mount subdir_not_there -s $H0 --volfile-id $V0 $M1; + +# mount subdir with depth +TEST $GFS --subdir-mount /subdir1/subdir1.1/subdir1.2 -s $H0 --volfile-id $V0 $M2; +TEST ! stat $M2/topfile; +TEST touch $M2/subdir1.2_file; +TEST ! stat $M0/subdir1.2_file; +TEST stat $M0/subdir1/subdir1.1/subdir1.2/subdir1.2_file; + +TEST umount $M2 + +# Lets validate the options # Not having '*' in here as there was some +# problem with option validation with this +TEST $CLI volume set $V0 auth.allow 192.168.1.1 + +TEST $CLI volume set $V0 auth.allow "192.168.1.1,10.10.\*.\*,::1" + +TEST $CLI volume set $V0 auth.allow "/subdir1\(1.2.3.4\),/\(192.168.10.2\|192.168.11.1\),/subdir2\(1.2.3.4\)" + +# directories should be absolute +TEST ! $CLI volume set $V0 auth.allow "subdir2\(1.2.3.4\)" + +# support subdir inside subdir +TEST $CLI volume set $V0 auth.allow '/subdir1/subdir1.1/subdir1.2/\(1.2.3.4\|::1\),/\(192.168.10.1\|192.168.11.1\),/subdir2\(1.2.3.4\)' + +TEST $CLI volume stop $V0 + +TEST $CLI volume start $V0 + +TEST $GFS --subdir-mount /subdir1/subdir1.1/subdir1.2 -s $H0 --volfile-id $V0 $M2 +TEST stat $M2 + +initcnt=`grep -i create-subdir-mounts /var/log/glusterfs/glusterd.log | wc -l` +# mount shouldn't fail even after add-brick +TEST $CLI volume add-brick $V0 replica 2 $H0:$B0/${V0}{5,6}; + +# Wait to execute create-subdir-mounts.sh script by glusterd +newcnt=`grep -i create-subdir-mounts /var/log/glusterfs/glusterd.log | wc -l` +while [ $newcnt -eq $initcnt ] +do + newcnt=`grep -i create-subdir-mounts /var/log/glusterfs/glusterd.log | wc -l` + sleep 1 +done + +# Existing mount should still be active +mount_inode=$(stat --format "%i" "$M2") +TEST test "$mount_inode" == "1" + +TEST umount $M2 + +# Now the exported subdirs should be automatically healed due to +# hook scripts. Check if the mount is successful. +TEST $GFS --subdir-mount /subdir2 -s $H0 --volfile-id $V0 $M2 +mount_inode=$(stat --format "%i" "$M2") +TEST test "$mount_inode" == "1" + +TEST umount $M0 +TEST umount $M2 + + +TEST $CLI volume stop $V0; +TEST $CLI volume delete $V0; +TEST ! $CLI volume info $V0; + +## This should clean the mountpoints +cleanup; diff --git a/tests/features/trash.t b/tests/features/trash.t index 620b84f0da1..da5b50bc85a 100755 --- a/tests/features/trash.t +++ b/tests/features/trash.t @@ -2,6 +2,7 @@ . $(dirname $0)/../include.rc . $(dirname $0)/../volume.rc +. $(dirname $0)/../dht.rc cleanup @@ -93,152 +94,149 @@ wildcard_not_exists() { if [ $? -eq 0 ]; then echo "Y"; else echo "N"; fi } -# testing glusterd [1-3] +# testing glusterd TEST glusterd TEST pidof glusterd TEST $CLI volume info -# creating distributed volume [4] +# creating distributed volume TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2} -# checking volume status [5-7] +# checking volume status EXPECT "$V0" volinfo_field $V0 'Volume Name' EXPECT 'Created' volinfo_field $V0 'Status' EXPECT '2' brick_count $V0 -# test without enabling trash translator [8] +# test without enabling trash translator TEST start_vol $V0 $M0 -# test on enabling trash translator [9-10] +# test on enabling trash translator TEST $CLI volume set $V0 features.trash on EXPECT 'on' volinfo_field $V0 'features.trash' -# files directly under mount point [11] +# files directly under mount point create_files $M0/file1 $M0/file2 TEST file_exists $V0 file1 file2 -# perform unlink [12] +# perform unlink TEST unlink_op file1 -# perform truncate [13] +# perform truncate TEST truncate_op file2 4 -# create files directory hierarchy and check [14] +# create files directory hierarchy and check mkdir -p $M0/1/2/3 create_files $M0/1/2/3/foo1 $M0/1/2/3/foo2 TEST file_exists $V0 1/2/3/foo1 1/2/3/foo2 -# perform unlink [15] +# perform unlink TEST unlink_op 1/2/3/foo1 -# perform truncate [16] +# perform truncate TEST truncate_op 1/2/3/foo2 4 # create a directory for eliminate pattern mkdir $M0/a -# set the eliminate pattern [17-18] +# set the eliminate pattern TEST $CLI volume set $V0 features.trash-eliminate-path /a EXPECT '/a' volinfo_field $V0 'features.trash-eliminate-path' -# create two files and check [19] +# create two files and check create_files $M0/a/test1 $M0/a/test2 TEST file_exists $V0 a/test1 a/test2 -# remove from eliminate pattern [20] +# remove from eliminate pattern rm -f $M0/a/test1 EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test1* -# truncate from eliminate path [21-23] +# truncate from eliminate path truncate -s 2 $M0/a/test2 TEST [ -e $M0/a/test2 ] TEST [ `ls -l $M0/a/test2 | awk '{print $5}'` -eq 2 ] EXPECT "Y" wildcard_not_exists $M0/.trashcan/a/test2* -# set internal op on [24-25] +# set internal op on TEST $CLI volume set $V0 features.trash-internal-op on EXPECT 'on' volinfo_field $V0 'features.trash-internal-op' -# again create two files and check [26] +# again create two files and check create_files $M0/inop1 $M0/inop2 TEST file_exists $V0 inop1 inop2 -# perform unlink [27] +# perform unlink TEST unlink_op inop1 -# perform truncate [28] +# perform truncate TEST truncate_op inop2 4 -# remove one brick and restart the volume [28-31] +# remove one brick and restart the volume TEST $CLI volume remove-brick $V0 $H0:$B0/${V0}2 force EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 TEST $CLI volume stop $V0 TEST start_vol $V0 $M0 $M0/.trashcan -# again create two files and check [33] +# again create two files and check create_files $M0/rebal1 $M0/rebal2 TEST file_exists $V0 rebal1 rebal2 -# add one brick [34-35] +# add one brick TEST $CLI volume add-brick $V0 $H0:$B0/${V0}3 TEST [ -d $B0/${V0}3 ] -# perform rebalance [36] + +# perform rebalance TEST $CLI volume rebalance $V0 start force +EXPECT_WITHIN $REBALANCE_TIMEOUT "0" rebalance_completed + +#Find out which file was migrated to the new brick +file_name=$(ls $B0/${V0}3/rebal*| xargs basename) + +# check whether rebalance was succesful +EXPECT "Y" wildcard_exists $B0/${V0}3/$file_name* +EXPECT "Y" wildcard_exists $B0/${V0}1/.trashcan/internal_op/$file_name* -# check whether rebalance was succesful [37-40] -EXPECT_WITHIN $REBALANCE_TIMEOUT "Y" wildcard_exists $B0/${V0}3/rebal2 -EXPECT_WITHIN $REBALANCE_TIMEOUT "Y" wildcard_exists $B0/${V0}1/.trashcan/internal_op/rebal2* EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + # force required in case rebalance is not over TEST $CLI volume stop $V0 force -# create a replicated volume [41] +# create a replicated volume TEST $CLI volume create $V1 replica 2 $H0:$B0/${V1}{1,2} -# checking volume status [42-45] +# checking volume status EXPECT "$V1" volinfo_field $V1 'Volume Name' EXPECT 'Replicate' volinfo_field $V1 'Type' EXPECT 'Created' volinfo_field $V1 'Status' EXPECT '2' brick_count $V1 -# enable trash with options and start the replicate volume by disabling automatic self-heal [46-50] +# enable trash with options and start the replicate volume by disabling automatic self-heal TEST $CLI volume set $V1 features.trash on TEST $CLI volume set $V1 features.trash-internal-op on EXPECT 'on' volinfo_field $V1 'features.trash' EXPECT 'on' volinfo_field $V1 'features.trash-internal-op' TEST start_vol $V1 $M1 $M1/.trashcan -# mount and check for trash directory [51] +# mount and check for trash directory TEST [ -d $M1/.trashcan/internal_op ] -# create a file and check [52] +# create a file and check touch $M1/self TEST [ -e $B0/${V1}1/self -a -e $B0/${V1}2/self ] -# kill one brick and delete the file from mount point [53-54] +# kill one brick and delete the file from mount point kill_brick $V1 $H0 $B0/${V1}1 EXPECT_WITHIN ${PROCESS_UP_TIMEOUT} "1" online_brick_count rm -f $M1/self EXPECT "Y" wildcard_exists $B0/${V1}2/.trashcan/self* -# force start the volume and trigger the self-heal manually [55-57] -TEST $CLI volume start $V1 force -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" online_brick_count -EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status -# Since we created the file under root of the volume, it will be -# healed automatically - -# check for the removed file in trashcan [58] -EXPECT_WITHIN $HEAL_TIMEOUT "Y" wildcard_exists $B0/${V1}1/.trashcan/internal_op/self* - -# check renaming of trash directory through cli [59-62] +# check renaming of trash directory through cli TEST $CLI volume set $V0 trash-dir abc TEST start_vol $V0 $M0 $M0/abc TEST [ -e $M0/abc -a ! -e $M0/.trashcan ] -EXPECT "Y" wildcard_exists $B0/${V0}1/abc/internal_op/rebal2* +EXPECT "Y" wildcard_exists $B0/${V0}1/abc/internal_op/rebal* -# ensure that rename and delete operation on trash directory fails [63-65] +# ensure that rename and delete operation on trash directory fails rm -rf $M0/abc/internal_op TEST [ -e $M0/abc/internal_op ] rm -rf $M0/abc/ diff --git a/tests/features/unhashed-auto.t b/tests/features/unhashed-auto.t index ddebd03299d..0a6bbfbb07d 100755 --- a/tests/features/unhashed-auto.t +++ b/tests/features/unhashed-auto.t @@ -114,7 +114,7 @@ TEST [ x"$new_hash" = x"00000001" ] # Unset the option and check that newly created directories get 1 in the # disk layout -TEST $CLI volume reset $V0 cluster.lookup-optimize +TEST $CLI volume set $V0 cluster.lookup-optimize off TEST mkdir $M0/dir1 new_hash=$(get_xattr_hash $B0/${V0}1/dir1) TEST [ x"$new_hash" = x"00000001" ] diff --git a/tests/features/worm.t b/tests/features/worm.t index 407b49a79ce..40b08cdee02 100755 --- a/tests/features/worm.t +++ b/tests/features/worm.t @@ -48,6 +48,69 @@ TEST ! link $M0/file1 $M0/file2 sleep 5 TEST rm -f $M0/file1 +## Test for mv over WORM/Reatined state +TEST `echo "worm 1" > $M0/file1` +TEST chmod 0444 $M0/file1 +TEST `echo "worm 2" > $M0/file2` +TEST ! mv $M0/file2 $M0/file1 +TEST rm -f $M0/file2 +sleep 10 +TEST rm -f $M0/file1 + +## Test for state transition over write. +TEST `echo "worm 1" > $M0/file3` +sleep 5 +TEST `echo "worm 2" >> $M0/file3` +EXPECT 'worm 1' cat $M0/file3 +TEST ! rm -f $M0/file3 + +## Test for checking if Worm files are undeletable after setting worm-files-deletable as 0. +TEST $CLI volume set $V0 features.worm-files-deletable 0 +TEST `echo "worm 1" > $M0/file4` +TEST chmod 0444 $M0/file4 +sleep 10 +TEST `echo "worm 1" >> $M0/file4` +TEST ! rm -f $M0/file4 + +## Test for state transition if auto-commit-period is 0 +TEST $CLI volume set $V0 features.auto-commit-period 0 +TEST `echo "worm 1" > $M0/file5` +EXPECT '3/10/0' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file5) +EXPECT 'worm 1' cat $M0/file5 +TEST ! rm -f $M0/file5 +TEST $CLI volume set $V0 features.auto-commit-period 5 + +## Test for checking if retention-period is updated on increasing the access time of a WORM-RETAINED file. +TEST $CLI volume set $V0 features.worm-files-deletable 1 +TEST `echo "worm 1" >> $M0/file1` +initial_timestamp=$(date +%s) +current_time_seconds=$(date +%S | sed 's/^0*//' ); +TEST chmod 0444 $M0/file1 +EXPECT '3/10/5' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) +changed_timestamp=$(date +%Y%m%d%H%M --date '60 seconds'); +seconds_diff=`expr 60 - $((current_time_seconds))` +TEST `touch -a -t "${changed_timestamp}" $M0/file1` +EXPECT "3/$seconds_diff/5" echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) +sleep $seconds_diff +TEST `echo "worm 2" >> $M0/file1` +EXPECT "$initial_timestamp" echo $(stat --printf %X $M0/file1) + + +## Test for checking if retention-period is updated on decreasing the access time of a WORM-RETAINED file +TEST $CLI volume set $V0 features.default-retention-period 120 +initial_timestamp=$(date +%s) +current_time_seconds=$(date +%S | sed 's/^0*//' ); +TEST chmod 0444 $M0/file1 +EXPECT '3/120/5' echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) +changed_timestamp=$(date +%Y%m%d%H%M --date '60 seconds'); +seconds_diff=`expr 60 - $((current_time_seconds))` +TEST `touch -a -t "${changed_timestamp}" $M0/file1` +EXPECT "3/$seconds_diff/5" echo $(getfattr -e text --absolute-names --only-value -n "trusted.reten_state" $B0/${V0}1/file1) +sleep $seconds_diff +TEST `echo "worm 4" >> $M0/file1` +EXPECT "$initial_timestamp" echo $(stat --printf %X $M0/file1) +TEST rm -f $M0/file1 + TEST $CLI volume stop $V0 EXPECT 'Stopped' volinfo_field $V0 'Status' diff --git a/tests/features/worm_sh.t b/tests/features/worm_sh.t new file mode 100644 index 00000000000..da7afc084b2 --- /dev/null +++ b/tests/features/worm_sh.t @@ -0,0 +1,75 @@ +#!/bin/bash +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume start $V0 +TEST $CLI volume set $V0 cluster.data-self-heal off +TEST $CLI volume set $V0 cluster.metadata-self-heal off +TEST $CLI volume set $V0 cluster.entry-self-heal off + +TEST $CLI volume set $V0 self-heal-daemon off +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; + +## Enable file level WORM +TEST $CLI volume set $V0 features.worm-file-level 1 +TEST $CLI volume set $V0 features.default-retention-period 100 +TEST $CLI volume set $V0 features.auto-commit-period 5 + +## Tests for manual transition to WORM/Retained state +TEST `echo "worm1" > $M0/file1` +TEST chmod 0444 $M0/file1 +sleep 5 +TEST `echo "worm2" > $M0/file2` +TEST chmod 0444 $M0/file2 +sleep 5 +TEST `echo "worm3" > $M0/file3` +TEST chmod 0444 $M0/file3 +sleep 5 + +## Stopp one of the bricks +TEST kill_brick $V0 $H0 $B0/${V0}1 + +## Manipulate the WORMed-Files +TEST $CLI volume set $V0 features.worm-file-level 0 +sleep 5 + +TEST chmod 0777 $M0/file1 +TEST `echo "test" >> $M0/file1` +TEST `echo "test" >> $M0/file3` +TEST `rm -rf $M0/file2` + +## Metadata changes +TEST setfattr -n user.test -v qwerty $M0/file3 +sleep 5 + +## Enable file level WORM again +TEST $CLI volume set $V0 features.worm-file-level 1 + +## Restart volume and trigger self-heal +TEST $CLI volume stop $V0 force +TEST $CLI volume start $V0 force +TEST $CLI volume set $V0 self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +TEST $CLI volume heal $V0 + +# Wait for heal to complete +EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0 + +# Check if entry-heal has happened +TEST diff <(ls $B0/${V0}0 | sort) <(ls $B0/${V0}1 | sort) + +# Test if data was healed +TEST diff $B0/${V0}0/file1 $B0/${V0}1/file1 +TEST diff $B0/${V0}0/file3 $B0/${V0}1/file3 + +# Test if metadata was healed and exists on both the bricks +EXPECT "qwerty" get_text_xattr user.test $B0/${V0}1/file3 +EXPECT "qwerty" get_text_xattr user.test $B0/${V0}0/file3 + +cleanup; |
