diff --git a/test/lvol/common.sh b/test/lvol/common.sh index 582fd1b13..8b5a51ea0 100644 --- a/test/lvol/common.sh +++ b/test/lvol/common.sh @@ -1,5 +1,7 @@ MALLOC_SIZE_MB=128 MALLOC_BS=512 +AIO_SIZE_MB=400 +AIO_BS=4096 LVS_DEFAULT_CLUSTER_SIZE_MB=4 LVS_DEFAULT_CLUSTER_SIZE=$(( LVS_DEFAULT_CLUSTER_SIZE_MB * 1024 * 1024 )) # reserve some MBs for lvolstore metadata @@ -18,5 +20,9 @@ function check_leftover_devices() { } function round_down() { - echo $(( $1 / LVS_DEFAULT_CLUSTER_SIZE_MB * LVS_DEFAULT_CLUSTER_SIZE_MB )) + local CLUSTER_SIZE_MB=$LVS_DEFAULT_CLUSTER_SIZE_MB + if [ -n "$2" ]; then + CLUSTER_SIZE_MB=$2 + fi + echo $(( $1 / CLUSTER_SIZE_MB * CLUSTER_SIZE_MB )) } diff --git a/test/lvol/lvol.sh b/test/lvol/lvol.sh index 3a250934c..106ec9fb1 100755 --- a/test/lvol/lvol.sh +++ b/test/lvol/lvol.sh @@ -35,9 +35,6 @@ function usage() { 653: 'thin_provisioning_resize', 654: 'thin_overprovisioning', 655: 'thin_provisioning_filling_disks_less_than_lvs_size', - 700: 'tasting_positive', - 701: 'tasting_lvol_store_positive', - 702: 'tasting_positive_with_different_lvol_store_cluster_size', 750: 'snapshot_readonly', 751: 'snapshot_compare_with_lvol_bdev', 752: 'snapshot_during_io_traffic', diff --git a/test/lvol/lvol2.sh b/test/lvol/lvol2.sh index 80e28db7a..37ad15794 100755 --- a/test/lvol/lvol2.sh +++ b/test/lvol/lvol2.sh @@ -10,6 +10,7 @@ timing_enter basic run_test "lvol_basic" test/lvol/basic.sh run_test "lvol_resize" test/lvol/resize.sh run_test "lvol_hotremove" test/lvol/hotremove.sh +run_test "lvol_tasting" test/lvol/tasting.sh timing_exit basic timing_exit lvol diff --git a/test/lvol/tasting.sh b/test/lvol/tasting.sh new file mode 100755 index 000000000..ac6898e41 --- /dev/null +++ b/test/lvol/tasting.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash + +testdir=$(readlink -f $(dirname $0)) +rootdir=$(readlink -f $testdir/../..) +source $rootdir/test/common/autotest_common.sh +source $rootdir/test/lvol/common.sh + +# Make sure lvol stores are automatically detected after base bdev detach and subsequent attach +function test_tasting() { + # Create two aio bdevs + rpc_cmd bdev_aio_create $testdir/aio_bdev_0 aio_bdev0 "$AIO_BS" + rpc_cmd bdev_aio_create $testdir/aio_bdev_1 aio_bdev1 "$AIO_BS" + # Create a valid lvs + lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore aio_bdev0 lvs_test) + # Destroy lvol store + rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" + # Remove the lvol stores and make sure it's not being automatically detected after base + # bdev re-attach. + rpc_cmd bdev_aio_delete aio_bdev0 + # Create aio bdev on the same file + rpc_cmd bdev_aio_create $testdir/aio_bdev_0 aio_bdev0 "$AIO_BS" + sleep 1 + # Check if destroyed lvol store does not exist on aio bdev + rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false + + # Create a valid lvs + lvs1_cluster_size=$(( 1 * 1024 * 1024 )) + lvs2_cluster_size=$(( 32 * 1024 * 1024 )) + lvs_uuid1=$(rpc_cmd bdev_lvol_create_lvstore aio_bdev0 lvs_test1 -c $lvs1_cluster_size) + lvs_uuid2=$(rpc_cmd bdev_lvol_create_lvstore aio_bdev1 lvs_test2 -c $lvs2_cluster_size) + + # Create 5 lvols on first lvs + lvol_size_mb=$(round_down $(( LVS_DEFAULT_CAPACITY_MB / 10 ))) + lvol_size=$(( lvol_size_mb * 1024 * 1024 )) + + for i in $(seq 1 5); do + lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid1" "lvol_test${i}" "$lvol_size_mb") + lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") + + [ "$(jq -r '.[0].name' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].uuid' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].aliases[0]' <<< "$lvol")" = "lvs_test1/lvol_test${i}" ] + [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$AIO_BS" ] + [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$(( lvol_size / AIO_BS ))" ] + done + + # Create 5 lvols on second lvs + lvol2_size_mb=$(round_down $(( ( AIO_SIZE_MB - 16 ) / 5 )) 32) + lvol2_size=$(( lvol2_size_mb * 1024 * 1024 )) + + for i in $(seq 1 5); do + lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid2" "lvol_test${i}" "$lvol2_size_mb") + lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") + + [ "$(jq -r '.[0].name' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].uuid' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].aliases[0]' <<< "$lvol")" = "lvs_test2/lvol_test${i}" ] + [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$AIO_BS" ] + [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$(( lvol2_size / AIO_BS ))" ] + done + + old_lvols=$(rpc_cmd bdev_get_bdevs | jq -r '[ .[] | select(.product_name == "Logical Volume") ]') + [ "$(jq length <<< "$old_lvols")" == "10" ] + old_lvs=$(rpc_cmd bdev_lvol_get_lvstores | jq .) + + # Restart spdk app + killprocess $spdk_pid + $rootdir/app/spdk_tgt/spdk_tgt & + spdk_pid=$! + waitforlisten $spdk_pid + + # Create aio bdevs + rpc_cmd bdev_aio_create $testdir/aio_bdev_0 aio_bdev0 "$AIO_BS" + rpc_cmd bdev_aio_create $testdir/aio_bdev_1 aio_bdev1 "$AIO_BS" + sleep 1 + + # Check tasting feature + new_lvols=$(rpc_cmd bdev_get_bdevs | jq -r '[ .[] | select(.product_name == "Logical Volume") ]') + [ "$(jq length <<< "$new_lvols")" == "10" ] + new_lvs=$(rpc_cmd bdev_lvol_get_lvstores | jq .) + if ! diff <(jq -S . <<<"$old_lvs") <(jq -S . <<<"$new_lvs"); then + echo "ERROR: old and loaded lvol store is not the same" + return 1 + fi + if ! diff <(jq -S . <<<"$old_lvols") <(jq -S . <<<"$new_lvols"); then + echo "ERROR: old and loaded lvols are not the same" + return 1 + fi + + # Check if creation and deletion lvol bdevs on lvs is possible + for i in $(seq 6 10); do + lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid1" "lvol_test${i}" "$lvol_size_mb") + lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") + + [ "$(jq -r '.[0].name' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].uuid' <<< "$lvol")" = "$lvol_uuid" ] + [ "$(jq -r '.[0].aliases[0]' <<< "$lvol")" = "lvs_test1/lvol_test${i}" ] + [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$AIO_BS" ] + [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$(( lvol_size / AIO_BS ))" ] + done + + for i in $(seq 1 10); do + rpc_cmd bdev_lvol_delete "lvs_test1/lvol_test${i}" + done + + rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid1" + + # Create an lvstore and 10 lvol on top to see if deletion of such struct works as it should. + lvs_uuid1=$(rpc_cmd bdev_lvol_create_lvstore aio_bdev0 lvs_test1) + for i in $(seq 1 10); do + rpc_cmd bdev_lvol_create -u "$lvs_uuid1" "lvol_test${i}" "$lvol_size_mb" + done + + # Clean up + rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid1" + rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid1" && false + rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid2" + rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid2" && false + rpc_cmd bdev_aio_delete aio_bdev0 + rpc_cmd bdev_aio_delete aio_bdev1 + check_leftover_devices +} + +$rootdir/app/spdk_tgt/spdk_tgt & +spdk_pid=$! +trap 'killprocess "$spdk_pid"; rm -f $testdir/aio_bdev_0 $testdir/aio_bdev_1; exit 1' SIGINT SIGTERM EXIT +waitforlisten $spdk_pid +truncate -s "${AIO_SIZE_MB}M" $testdir/aio_bdev_0 $testdir/aio_bdev_1 + +run_test "test_tasting" test_tasting + +trap - SIGINT SIGTERM EXIT +killprocess $spdk_pid +rm -f $testdir/aio_bdev_0 $testdir/aio_bdev_1 diff --git a/test/lvol/test_cases.py b/test/lvol/test_cases.py index 8f033d62a..c9cf8dbc3 100644 --- a/test/lvol/test_cases.py +++ b/test/lvol/test_cases.py @@ -125,10 +125,6 @@ def case_message(func): 653: 'thin_provisioning_resize', 654: 'thin_overprovisioning', 655: 'thin_provisioning_filling_disks_less_than_lvs_size', - # logical volume tasting tests - 700: 'tasting_positive', - 701: 'tasting_lvol_store_positive', - 702: 'tasting_positive_with_different_lvol_store_cluster_size', # snapshot and clone 750: 'snapshot_readonly', 751: 'snapshot_compare_with_lvol_bdev', @@ -992,282 +988,6 @@ class TestCases(object): # - no other operation fails return fail_count - @case_message - def test_case700(self): - """ - tasting_positive - - Positive test for tasting a multi lvol bdev configuration. - Create a lvol store with some lvol bdevs on aio bdev and restart vhost app. - After restarting configuration should be automatically loaded and should be exactly - the same as before restarting. - Check that running configuration can be modified after restarting and tasting. - """ - fail_count = 0 - uuid_bdevs = [] - base_name = "aio_bdev0" - - base_path = path.dirname(sys.argv[0]) - vhost_path = path.join(self.app_path, 'vhost') - pid_path = path.join(base_path, 'vhost.pid') - aio_bdev0 = path.join(base_path, 'aio_bdev_0') - - self.c.bdev_aio_create(aio_bdev0, base_name, 4096) - # Create initial configuration on running vhost instance - # create lvol store, create 5 bdevs - # save info of all lvs and lvol bdevs - uuid_store = self.c.bdev_lvol_create_lvstore(base_name, - self.lvs_name) - fail_count += self.c.check_bdev_lvol_get_lvstores(base_name, - uuid_store, - self.cluster_size) - - size = self.get_lvs_divided_size(10) - - for i in range(5): - uuid_bdev = self.c.bdev_lvol_create(uuid_store, - self.lbd_name + str(i), - size) - uuid_bdevs.append(uuid_bdev) - # Using bdev_get_bdevs command verify lvol bdevs were correctly created - fail_count += self.c.check_bdev_get_bdevs_methods(uuid_bdev, size) - - old_bdevs = sorted(self.c.get_lvol_bdevs(), key=lambda x: x["name"]) - old_stores = self.c.bdev_lvol_get_lvstores() - - # Shut down vhost instance and restart with new instance - fail_count += self._stop_vhost(pid_path) - remove(pid_path) - if self._start_vhost(vhost_path, pid_path) != 0: - fail_count += 1 - return fail_count - - self.c.bdev_aio_create(aio_bdev0, base_name, 4096) - # Check if configuration was properly loaded after tasting - # get all info all lvs and lvol bdevs, compare with previous info - new_bdevs = sorted(self.c.get_lvol_bdevs(), key=lambda x: x["name"]) - new_stores = self.c.bdev_lvol_get_lvstores() - - if old_stores != new_stores: - fail_count += 1 - print("ERROR: old and loaded lvol store is not the same") - print("DIFF:") - print(old_stores) - print(new_stores) - - if len(old_bdevs) != len(new_bdevs): - fail_count += 1 - print("ERROR: old and loaded lvol bdev list count is not equal") - - for o, n in zip(old_bdevs, new_bdevs): - if o != n: - fail_count += 1 - print("ERROR: old and loaded lvol bdev is not the same") - print("DIFF:") - pprint.pprint([o, n]) - - if fail_count != 0: - self.c.bdev_aio_delete(aio_bdev0) - return fail_count - - # Try modifying loaded configuration - # Add some lvol bdevs to existing lvol store then - # remove all lvol configuration and re-create it again - for i in range(5, 10): - uuid_bdev = self.c.bdev_lvol_create(uuid_store, - self.lbd_name + str(i), - size) - uuid_bdevs.append(uuid_bdev) - fail_count += self.c.check_bdev_get_bdevs_methods(uuid_bdev, size) - - for uuid_bdev in uuid_bdevs: - self.c.bdev_lvol_delete(uuid_bdev) - - if self.c.bdev_lvol_delete_lvstore(uuid_store) != 0: - fail_count += 1 - - uuid_bdevs = [] - - # Create lvol store on aio bdev, create ten lvol bdevs on lvol store and - # verify all configuration call results - uuid_store = self.c.bdev_lvol_create_lvstore(base_name, - self.lvs_name) - fail_count += self.c.check_bdev_lvol_get_lvstores(base_name, - uuid_store, - self.cluster_size) - - for i in range(10): - uuid_bdev = self.c.bdev_lvol_create(uuid_store, - self.lbd_name + str(i), - size) - uuid_bdevs.append(uuid_bdev) - fail_count += self.c.check_bdev_get_bdevs_methods(uuid_bdev, size) - - # Destroy lvol store - if self.c.bdev_lvol_delete_lvstore(uuid_store) != 0: - fail_count += 1 - - self.c.bdev_aio_delete(base_name) - - return fail_count - - @case_message - def test_case701(self): - """ - tasting_lvol_store_positive - - Positive test for tasting lvol store. - """ - base_path = path.dirname(sys.argv[0]) - aio_bdev0 = path.join(base_path, 'aio_bdev_0') - base_name = "aio_bdev0" - - self.c.bdev_aio_create(aio_bdev0, base_name, 4096) - # construct lvol store on aio bdev - uuid_store = self.c.bdev_lvol_create_lvstore(base_name, - self.lvs_name) - fail_count = self.c.check_bdev_lvol_get_lvstores(base_name, uuid_store, - self.cluster_size) - - self.c.bdev_aio_delete(base_name) - self.c.bdev_aio_create(aio_bdev0, base_name, 4096) - # wait 1 second to allow time for lvolstore tasting - sleep(1) - # check if lvol store still exists in vhost configuration - if self.c.check_bdev_lvol_get_lvstores(base_name, uuid_store, - self.cluster_size) != 0: - fail_count += 1 - # destroy lvol store from aio bdev - if self.c.bdev_lvol_delete_lvstore(uuid_store) != 0: - fail_count += 1 - - self.c.bdev_aio_delete(base_name) - return fail_count - - @case_message - def test_case702(self): - """ - tasting_positive_with_different_lvol_store_cluster_size - - Positive test for tasting a multi lvol bdev configuration. - Create two lvol stores with different cluster sizes with some lvol bdevs on aio - drive and restart vhost app. - After restarting configuration should be automatically loaded and should be exactly - the same as before restarting. - """ - fail_count = 0 - uuid_bdevs = [] - cluster_size_1M = MEGABYTE - cluster_size_32M = 32 * MEGABYTE - base_name_1M = "aio_bdev0" - base_name_32M = "aio_bdev1" - - base_path = path.dirname(sys.argv[0]) - vhost_path = path.join(self.app_path, 'vhost') - pid_path = path.join(base_path, 'vhost.pid') - aio_bdev0 = path.join(base_path, 'aio_bdev_0') - aio_bdev1 = path.join(base_path, 'aio_bdev_1') - - self.c.bdev_aio_create(aio_bdev0, base_name_1M, 4096) - self.c.bdev_aio_create(aio_bdev1, base_name_32M, 4096) - - # Create initial configuration on running vhost instance - # create lvol store, create 5 bdevs - # save info of all lvs and lvol bdevs - uuid_store_1M = self.c.bdev_lvol_create_lvstore(base_name_1M, - self.lvs_name + "_1M", - cluster_size_1M) - - fail_count += self.c.check_bdev_lvol_get_lvstores(base_name_1M, - uuid_store_1M, - cluster_size_1M) - - uuid_store_32M = self.c.bdev_lvol_create_lvstore(base_name_32M, - self.lvs_name + "_32M", - cluster_size_32M) - - fail_count += self.c.check_bdev_lvol_get_lvstores(base_name_32M, - uuid_store_32M, - cluster_size_32M) - - # size = approx 20% of total aio bdev size - size_1M = self.get_lvs_divided_size(5, self.lvs_name + "_1M") - size_32M = self.get_lvs_divided_size(5, self.lvs_name + "_32M") - - for i in range(5): - uuid_bdev = self.c.bdev_lvol_create(uuid_store_1M, - self.lbd_name + str(i) + "_1M", - size_1M) - uuid_bdevs.append(uuid_bdev) - # Using bdev_get_bdevs command verify lvol bdevs were correctly created - fail_count += self.c.check_bdev_get_bdevs_methods(uuid_bdev, size_1M) - - for i in range(5): - uuid_bdev = self.c.bdev_lvol_create(uuid_store_32M, - self.lbd_name + str(i) + "_32M", - size_32M) - uuid_bdevs.append(uuid_bdev) - # Using bdev_get_bdevs command verify lvol bdevs were correctly created - fail_count += self.c.check_bdev_get_bdevs_methods(uuid_bdev, size_32M) - - old_bdevs = sorted(self.c.get_lvol_bdevs(), key=lambda x: x["name"]) - old_stores = sorted(self.c.bdev_lvol_get_lvstores(), key=lambda x: x["name"]) - - # Shut down vhost instance and restart with new instance - fail_count += self._stop_vhost(pid_path) - remove(pid_path) - if self._start_vhost(vhost_path, pid_path) != 0: - fail_count += 1 - return fail_count - - self.c.bdev_aio_create(aio_bdev0, base_name_1M, 4096) - self.c.bdev_aio_create(aio_bdev1, base_name_32M, 4096) - - # wait 1 second to allow time for lvolstore tasting - sleep(1) - - # Check if configuration was properly loaded after tasting - # get all info all lvs and lvol bdevs, compare with previous info - new_bdevs = sorted(self.c.get_lvol_bdevs(), key=lambda x: x["name"]) - new_stores = sorted(self.c.bdev_lvol_get_lvstores(), key=lambda x: x["name"]) - - if old_stores != new_stores: - fail_count += 1 - print("ERROR: old and loaded lvol store is not the same") - print("DIFF:") - print(old_stores) - print(new_stores) - - if len(old_bdevs) != len(new_bdevs): - fail_count += 1 - print("ERROR: old and loaded lvol bdev list count is not equal") - - for o, n in zip(old_bdevs, new_bdevs): - if o != n: - fail_count += 1 - print("ERROR: old and loaded lvol bdev is not the same") - print("DIFF:") - pprint.pprint([o, n]) - - if fail_count != 0: - self.c.bdev_aio_delete(base_name_1M) - self.c.bdev_aio_delete(base_name_32M) - return fail_count - - for uuid_bdev in uuid_bdevs: - self.c.bdev_lvol_delete(uuid_bdev) - - if self.c.bdev_lvol_delete_lvstore(uuid_store_1M) != 0: - fail_count += 1 - - if self.c.bdev_lvol_delete_lvstore(uuid_store_32M) != 0: - fail_count += 1 - - self.c.bdev_aio_delete(base_name_1M) - self.c.bdev_aio_delete(base_name_32M) - - return fail_count - @case_message def test_case750(self): """