diff --git a/test/lvol/test_cases.py b/test/lvol/test_cases.py index bf0db1eb9..0d8ec1df8 100644 --- a/test/lvol/test_cases.py +++ b/test/lvol/test_cases.py @@ -21,6 +21,26 @@ MEGABYTE = 1024 * 1024 current_fio_pid = -1 +# ## Objective +# The purpose of these tests is to verify the possibility of using lvol configuration in SPDK. +# +# ## Methodology +# Configuration in test is to be done using example stub application. +# All management is done using RPC calls, including logical volumes management. +# All tests are performed using malloc backends. +# One exception to malloc backends are tests for logical volume +# tasting - these require persistent merory like NVMe backend. +# +# Tests will be executed as scenarios - sets of smaller test step +# in which return codes from RPC calls is validated. +# Some configuration calls may also be validated by use of +# "get_*" RPC calls, which provide additional information for verifying +# results. +# +# Tests with thin provisioned lvol bdevs, snapshots and clones are using nbd devices. +# Before writing/reading to lvol bdev, bdev is installed with rpc start_nbd_disk. +# After finishing writing/reading, rpc stop_nbd_disk is used. + def is_process_alive(pid): try: @@ -90,30 +110,41 @@ def test_counter(): def case_message(func): def inner(*args, **kwargs): test_name = { + # construct_lvol_store - positive tests 1: 'construct_lvs_positive', + # construct_lvol_bdev - positive tests 50: 'construct_logical_volume_positive', 51: 'construct_multi_logical_volumes_positive', 52: 'construct_lvol_bdev_using_name_positive', 53: 'construct_lvol_bdev_duplicate_names_positive', + # construct_lvol_bdev - negative tests 100: 'construct_logical_volume_nonexistent_lvs_uuid', 101: 'construct_lvol_bdev_on_full_lvol_store', 102: 'construct_lvol_bdev_name_twice', + # resize_lvol_store - positive tests 150: 'resize_lvol_bdev_positive', + # resize lvol store - negative tests 200: 'resize_logical_volume_nonexistent_logical_volume', 201: 'resize_logical_volume_with_size_out_of_range', + # destroy_lvol_store - positive tests 250: 'destroy_lvol_store_positive', 251: 'destroy_lvol_store_use_name_positive', 252: 'destroy_lvol_store_with_lvol_bdev_positive', 253: 'destroy_multi_logical_volumes_positive', 254: 'destroy_after_resize_lvol_bdev_positive', 255: 'delete_lvol_store_persistent_positive', + # destroy_lvol_store - negative tests 300: 'destroy_lvol_store_nonexistent_lvs_uuid', 301: 'delete_lvol_store_underlying_bdev', + # nested destroy_lvol_bdev - negative tests 350: 'nested_destroy_logical_volume_negative', + # nested construct_logical_volume - positive tests 400: 'nested_construct_logical_volume_positive', + # construct_lvol_store - negative tests 450: 'construct_lvs_nonexistent_bdev', 451: 'construct_lvs_on_bdev_twice', 452: 'construct_lvs_name_twice', + # nested construct_lvol_bdev - test negative 500: 'nested_construct_lvol_bdev_on_full_lvol_store', 550: 'delete_bdev_positive', 551: 'delete_lvol_bdev', @@ -121,15 +152,18 @@ def case_message(func): 553: 'unregister_lvol_bdev', 600: 'construct_lvol_store_with_cluster_size_max', 601: 'construct_lvol_store_with_cluster_size_min', + # Provisioning 650: 'thin_provisioning_check_space', 651: 'thin_provisioning_read_empty_bdev', 652: 'thin_provisionind_data_integrity_test', 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', 752: 'snapshot_during_io_traffic', @@ -141,11 +175,13 @@ def case_message(func): 758: 'decouple_parent', 759: 'decouple_parent_rw', 760: 'set_read_only', + # logical volume rename tests 800: 'rename_positive', 801: 'rename_lvs_nonexistent', 802: 'rename_lvs_EEXIST', 803: 'rename_lvol_bdev_nonexistent', 804: 'rename_lvol_bdev_EEXIST', + # SIGTERM 10000: 'SIGTERM', } num = int(func.__name__.strip('test_case')[:]) @@ -282,48 +318,94 @@ class TestCases(object): # positive tests @case_message def test_case1(self): + """ + construct_lvs_positive + + Positive test for constructing a new lvol store. + Call construct_lvol_store with correct base bdev name. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct_lvol_store on correct, exisitng malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 + + # Expected result + # - call successful, return code = 0, uuid printed to stdout + # - get_lvol_stores: backend used for construct_lvol_store has uuid + # field set with the same uuid as returned from RPC call + # - no other operation fails return fail_count @case_message def test_case50(self): + """ + construct_logical_volume_positive + + Positive test for constructing a new logical volume. + Call construct_lvol_bdev with correct lvol store UUID and size in MiB for this bdev + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create lvol store on correct, exisitng malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) lvs_size = self.get_lvs_size() + # Construct lvol bdev on correct lvs_uuid and size uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, lvs_size) + # Check correct uuid values in response get_bdevs command fail_count += self.c.check_get_bdevs_methods(uuid_bdev, lvs_size) self.c.destroy_lvol_bdev(uuid_bdev) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - call successful, return code = 0 + # - get_lvol_store: backend used for construct_lvol_bdev has name + # field set with the same name as returned from RPC call for all repeat + # - no other operation fails return fail_count @case_message def test_case51(self): + """ + construct_multi_logical_volumes_positive + + Positive test for constructing a multi logical volumes. + Call construct_lvol_bdev with correct lvol store UUID and + size is equal one quarter of the this bdev size. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on correct, exisitng malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Verify lvol store was created correctly fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) size = self.get_lvs_divided_size(4) + # Repeat two times: + # - construct four lvol bdevs with 25% size of lvs size + # - verify if every lvol bdev was created correctly + # - delete four lvol bdevs for j in range(2): uuid_bdevs = [] for i in range(4): @@ -338,53 +420,85 @@ class TestCases(object): self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - calls successful, return code = 0 + # - no other operation fails return fail_count @case_message def test_case52(self): + """ + construct_lvol_bdev_using_name_positive + + Positive test for constructing a logical volume using friendly names. + Verify that logical volumes can be created by using a friendly name + instead of uuid when referencing to lvol store. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) - + # Construct lvol store uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) - + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) lvs_size = self.get_lvs_size() + # Create logical volume on lvol store by using a friendly name + # as a reference uuid_bdev = self.c.construct_lvol_bdev(self.lvs_name, self.lbd_name, lvs_size) + # Verify logical volume was correctly created fail_count += self.c.check_get_bdevs_methods(uuid_bdev, lvs_size) fail_count += self.c.destroy_lvol_bdev(uuid_bdev) fail_count += self.c.destroy_lvol_store(uuid_store) fail_count += self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - calls successful, return code = 0 + # - no other operation fails return fail_count @case_message def test_case53(self): + """ + construct_lvol_bdev_duplicate_names_positive + + Positive test for constructing a logical volumes using friendly names. + Verify that logical volumes can use the same argument for friendly names + if they are created on separate logical volume stores. + """ + # Construct two malloc bdevs base_name_1 = self.c.construct_malloc_bdev(self.total_size, self.block_size) base_name_2 = self.c.construct_malloc_bdev(self.total_size, self.block_size) - + # Create logical volume stores on created malloc bdevs uuid_store_1 = self.c.construct_lvol_store(base_name_1, self.lvs_name + "1") uuid_store_2 = self.c.construct_lvol_store(base_name_2, self.lvs_name + "2") + # Verify stores were created correctly fail_count = self.c.check_get_lvol_stores(base_name_1, uuid_store_1, self.cluster_size) fail_count = self.c.check_get_lvol_stores(base_name_2, uuid_store_2, self.cluster_size) lvs_size = self.get_lvs_size(self.lvs_name + "1") + # Create logical volume on first lvol store uuid_bdev_1 = self.c.construct_lvol_bdev(uuid_store_1, self.lbd_name, lvs_size) + # Using the same friendly name argument create logical volume on second + # lvol store uuid_bdev_2 = self.c.construct_lvol_bdev(uuid_store_2, self.lbd_name, lvs_size) + # Verify two lvol bdevs were correctly created fail_count += self.c.check_get_bdevs_methods(uuid_bdev_1, lvs_size) fail_count += self.c.check_get_bdevs_methods(uuid_bdev_2, lvs_size) @@ -394,31 +508,61 @@ class TestCases(object): fail_count += self.c.destroy_lvol_store(uuid_store_2) fail_count += self.c.delete_malloc_bdev(base_name_1) fail_count += self.c.delete_malloc_bdev(base_name_2) + + # Expected result: + # - calls successful, return code = 0 + # - no other operation fails return fail_count @case_message def test_case100(self): + """ + construct_logical_volume_nonexistent_lvs_uuid + + Negative test for constructing a new logical_volume. + Call construct_lvol_bdev with lvs_uuid which does not + exist in configuration. + """ fail_count = 0 + # Try to call construct_lvol_bdev with lvs_uuid which does not exist if self.c.construct_lvol_bdev(self._gen_lvs_uuid(), self.lbd_name, 32) == 0: fail_count += 1 + + # Expected result: + # - return code != 0 + # - ENODEV response printed to stdout return fail_count @case_message def test_case101(self): + """ + construct_lvol_bdev_on_full_lvol_store + + Negative test for constructing a new lvol bdev. + Call construct_lvol_bdev on a full lvol store. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create logical volume store on malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response from get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) lvs_size = self.get_lvs_size() + # Construct lvol bdev on correct lvs_uuid uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, lvs_size) + # Verify if lvol bdev was correctly created fail_count += self.c.check_get_bdevs_methods(uuid_bdev, lvs_size) + # Try construct lvol bdev on the same lvs_uuid as in last step + # This call should fail as lvol store space is taken by previously + # created bdev if self.c.construct_lvol_bdev(uuid_store, self.lbd_name + "_1", lvs_size) == 0: @@ -427,22 +571,41 @@ class TestCases(object): self.c.destroy_lvol_bdev(uuid_bdev) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - first call successful + # - second construct_lvol_bdev call return code != 0 + # - EEXIST response printed to stdout + # - no other operation fails return fail_count @case_message def test_case102(self): + """ + construct_lvol_bdev_name_twice + + Negative test for constructing lvol bdev using the same + friendly name twice on the same logical volume store. + """ + # Construct malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create logical volume store on malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Using get_lvol_stores verify that logical volume store was correctly created fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) size = self.get_lvs_size() + # Construct logical volume on lvol store and verify it was correctly created uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, size) fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) + # Try to create another logical volume on the same lvol store using + # the same friendly name as in previous step + # This step should fail if self.c.construct_lvol_bdev(uuid_store, self.lbd_name, size) == 0: @@ -451,243 +614,498 @@ class TestCases(object): self.c.destroy_lvol_bdev(uuid_bdev) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + + # Expected results: + # - creating two logical volumes with the same friendly name within the same + # lvol store should not be possible + # - no other operation fails return fail_count @case_message def test_case150(self): + """ + resize_logical_volume_positive + + + Positive test for resizing a logical_volume. + Call resize_lvol_bdev with correct logical_volumes name and new size. + """ + # Construct malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create lvol store uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Construct lvol bdev on correct lvs_uuid and # size is equal to one quarter of size malloc bdev - size = self.get_lvs_divided_size(4) uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, size) + # Check size of the lvol bdev by rpc command get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) + # Resize lvol bdev on correct lvs_uuid and # size is equal to half of size malloc bdev size = self.get_lvs_divided_size(2) self.c.resize_lvol_bdev(uuid_bdev, size) + # Check size of the lvol bdev by rpc command get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) + # Resize lvol bdev on the correct lvs_uuid and # size is smaller by 1 cluster size = (self.get_lvs_size() - self.get_lvs_cluster_size()) self.c.resize_lvol_bdev(uuid_bdev, size) + # Check size of the lvol bdev by rpc command get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) + # Resize lvol bdev on the correct lvs_uuid and # size is equal 0 MiB size = 0 self.c.resize_lvol_bdev(uuid_bdev, size) + # Check size of the lvol bdev by rpc command get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) self.c.destroy_lvol_bdev(uuid_bdev) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + # Expected result: + # - lvol bdev should change size after resize operations + # - calls successful, return code = 0 + # - no other operation fails return fail_count @case_message def test_case200(self): + """ + resize_logical_volume_nonexistent_logical_volume + + Negative test for resizing a logical_volume. + Call resize_lvol_bdev with logical volume which does not + exist in configuration. + """ fail_count = 0 + # Try resize lvol bdev on logical volume which does not exist if self.c.resize_lvol_bdev(self._gen_lvb_uuid(), 16) == 0: fail_count += 1 + + # Expected result: + # - return code != 0 + # - Error code: ENODEV ("No such device") response printed to stdout return fail_count @case_message def test_case201(self): + """ + resize_logical_volume_with_size_out_of_range + + Negative test for resizing a logical volume. + Call resize_lvol_store with size argument bigger than size of base bdev. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Construct_lvol_bdev on correct lvs_uuid and + # size is equal one quarter of size malloc bdev lvs_size = self.get_lvs_size() uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, lvs_size) fail_count += self.c.check_get_bdevs_methods(uuid_bdev, lvs_size) + # Try resize_lvol_bdev on correct lvs_uuid and size is + # equal to size malloc bdev + 1MiB; this call should fail if self.c.resize_lvol_bdev(uuid_bdev, self.total_size + 1) == 0: fail_count += 1 self.c.destroy_lvol_bdev(uuid_bdev) self.c.destroy_lvol_store(uuid_store) self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - resize_lvol_bdev call return code != 0 + # - Error code: ENODEV ("Not enough free clusters left on lvol store") + # response printed to stdout + # - no other operation fails return fail_count @case_message def test_case250(self): + """ + destroy_lvol_store_positive + + Positive test for destroying a logical volume store. + Call destroy_lvol_store with correct logical_volumes name + """ + # Construct malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Destroy lvol store self.c.destroy_lvol_store(uuid_store) + # Check correct response get_lvol_stores command if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - calls successful, return code = 0 + # - get_lvol_stores: response should be of no value after destroyed lvol store + # - no other operation fails return fail_count @case_message def test_case251(self): + """ + destroy_lvol_store_use_name_positive + + Positive test for destroying a logical volume store using + lvol store name instead of uuid for reference. + Call destroy_lvol_store with correct logical volume name + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Destroy lvol store fail_count += self.c.destroy_lvol_store(self.lvs_name) + # Check correct response get_lvol_stores command if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 fail_count += self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - calls successful, return code = 0 + # - get_lvol_stores: response should be of no value after destroyed lvol store + # - no other operation fails return fail_count @case_message def test_case252(self): + """ + destroy_lvol_store_with_lvol_bdev_positive + + Positive test for destroying a logical volume store with lvol bdev + created on top. + Call destroy_lvol_store with correct logical_volumes name + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Construct lvol bdev on correct lvs_uuid + # and size is equal to size malloc bdev lvs_size = self.get_lvs_size() uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, lvs_size) fail_count += self.c.check_get_bdevs_methods(uuid_bdev, lvs_size) + # Destroy lvol store if self.c.destroy_lvol_store(uuid_store) != 0: fail_count += 1 + # Check correct response get_lvol_stores command if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - calls successful, return code = 0 + # - get_lvol_stores: response should be of no value after destroyed lvol store + # - no other operation fails return fail_count @case_message def test_case253(self): + """ + Name: destroy_multi_logical_volumes_positive + + Positive test for destroying a logical volume store with multiple lvol + bdevs created on top. + Call construct_lvol_bdev with correct lvol store UUID and + size is equal to one quarter of the this bdev size. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on correct, exisitng malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) size = self.get_lvs_divided_size(4) - + # Construct four lvol bdevs on correct lvs_uuid and + # size is equal to one quarter of the lvol size for i in range(4): uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name + str(i), size) fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) + # Destroy lvol store self.c.destroy_lvol_store(uuid_store) + # Check correct response get_lvol_stores command if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - call successful, return code = 0 + # - get_lvol_store: backend used for construct_lvol_bdev has name + # field set with the same name as returned from RPC call for all repeat + # - no other operation fails return fail_count @case_message def test_case254(self): + """ + destroy_resize_logical_volume_positive + + Positive test for destroying a logical_volume after resizing. + Call destroy_lvol_store with correct logical_volumes name. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on create malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) size = self.get_lvs_divided_size(4) + # construct_lvol_bdev on correct lvs_uuid and size is + # equal to one quarter of size malloc bdev uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name, size) + # check size of the lvol bdev fail_count += self.c.check_get_bdevs_methods(uuid_bdev, size) - sz = size + 4 + # Resize_lvol_bdev on correct lvs_uuid and size is + # equal to one quarter of size malloc bdev plus 4 MB self.c.resize_lvol_bdev(uuid_bdev, sz) + # check size of the lvol bdev by command RPC : get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, sz) + # Resize_lvol_bdev on correct lvs_uuid and size is + # equal half of size malloc bdev sz = size * 2 self.c.resize_lvol_bdev(uuid_bdev, sz) + # check size of the lvol bdev by command RPC : get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, sz) + # Resize_lvol_bdev on correct lvs_uuid and size is + # equal to three quarters of size malloc bdev sz = size * 3 self.c.resize_lvol_bdev(uuid_bdev, sz) + # check size of the lvol bdev by command RPC : get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, sz) + # Resize_lvol_bdev on correct lvs_uuid and size is + # equal to size if malloc bdev minus 4 MB sz = (size * 4) - 4 self.c.resize_lvol_bdev(uuid_bdev, sz) + # check size of the lvol bdev by command RPC : get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, sz) + # Resize_lvol_bdev on the correct lvs_uuid and size is equal 0 MiB sz = 0 self.c.resize_lvol_bdev(uuid_bdev, sz) + # check size of the lvol bdev by command RPC : get_bdevs fail_count += self.c.check_get_bdevs_methods(uuid_bdev, sz) + # Destroy lvol store self.c.destroy_lvol_store(uuid_store) if self.c.check_get_lvol_stores("", "", "") == 1: fail_count += 1 self.c.delete_malloc_bdev(base_name) + + # Expected result: + # - lvol bdev should change size after resize operations + # - calls successful, return code = 0 + # - no other operation fails + # - get_lvol_stores: response should be of no value after destroyed lvol store return fail_count @case_message def test_case255(self): + """ + delete_lvol_store_persistent_positive + + Positive test for removing lvol store persistently + """ base_path = path.dirname(sys.argv[0]) base_name = "aio_bdev0" aio_bdev0 = path.join(base_path, "aio_bdev_0") + # Construct aio bdev self.c.construct_aio_bdev(aio_bdev0, base_name, 4096) + # Create lvol store on created aio bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Destroy lvol store if self.c.destroy_lvol_store(self.lvs_name) != 0: fail_count += 1 + # Delete aio bdev self.c.delete_aio_bdev(base_name) + # Create aio bdev on the same file self.c.construct_aio_bdev(aio_bdev0, base_name, 4096) - # wait 1 second to allow time for lvolstore tasting + # Wait 1 second to allow time for lvolstore tasting sleep(1) + # check if destroyed lvol store does not exist on aio bdev ret_value = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) if ret_value == 0: fail_count += 1 self.c.delete_aio_bdev(base_name) + + # Expected result: + # - get_lvol_stores should not report any existsing lvol stores in configuration + # after deleting and adding NVMe bdev + # - no other operation fails return fail_count @case_message def test_case300(self): + """ + destroy_lvol_store_nonexistent_lvs_uuid + + Call destroy_lvol_store with nonexistent logical_volumes name + exist in configuration. + """ fail_count = 0 + # try to call destroy_lvol_store with lvs_uuid which does not exist if self.c.destroy_lvol_store(self._gen_lvs_uuid()) == 0: fail_count += 1 + + # Expected result: + # - return code != 0 + # - Error code response printed to stdout return fail_count @case_message def test_case301(self): + """ + delete_lvol_store_underlying_bdev + + Call destroy_lvol_store after deleting it's base bdev. + Lvol store should be automatically removed on deleting underlying bdev. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Delete malloc bdev if self.c.delete_malloc_bdev(base_name) != 0: fail_count += 1 + # Try to destroy lvol store. This call should fail as lvol store + # is no longer present if self.c.destroy_lvol_store(uuid_store) == 0: fail_count += 1 + # Expected result: + # - destroy_lvol_store return code != 0 + # - Error code: ENODEV ("No such device") response printed to stdout + # - no other operation fails return fail_count def test_case350(self): print("Test of this feature not yet implemented.") - pass + # Name: nested_destroy_logical_volume_negative + # Negative test for destroying a nested first lvol store. + # all destroy_lvol_store with correct base bdev name. + # Steps: + # - create a malloc bdev + # - construct_lvol_store on created malloc bdev + # - check correct uuid values in response get_lvol_stores command + # - construct_lvol_bdev on correct lvs_uuid and size is + # equal to size malloc bdev + # - construct first nested lvol store on created lvol_bdev + # - check correct uuid values in response get_lvol_stores command + # - construct first nested lvol bdev on correct lvs_uuid and size + # - check size of the lvol bdev by command RPC : get_bdevs + # - destroy first lvol_store + # - delete malloc bdev + + # Expected result: + # - Error code: ENODEV ("the device is busy") response printed to stdout + # - no other operation fails return 0 def test_case400(self): print("Test of this feature not yet implemented.") - pass + # Name: nested_construct_logical_volume_positive + # Positive test for constructing a nested new lvol store. + # Call construct_lvol_store with correct base bdev name. + # Steps: + # - create a malloc bdev + # - construct_lvol_store on created malloc bdev + # - check correct uuid values in response get_lvol_stores command + # - construct_lvol_bdev on correct lvs_uuid and size is + # equal to size malloc bdev + # - construct first nested lvol store on created lvol_bdev + # - check correct uuid values in response get_lvol_stores command + # - construct first nested lvol bdev on correct lvs_uuid and size + # - construct second nested lvol store on created first nested lvol bdev + # - check correct uuid values in response get_lvol_stores command + # - construct second nested lvol bdev on correct first nested lvs uuid and size + # - delete nested lvol bdev and lvol store + # - delete base lvol bdev and lvol store + # - delete malloc bdev + + # Expected result: + # - calls successful, return code = 0 + # - get_lvol_stores: backend used for construct_lvol_store has UUID + # field set with the same UUID as returned from RPC call + # backend used for construct_lvol_bdev has UUID + # field set with the same UUID as returned from RPC call + # - no other operation fails return 0 # negative tests @case_message def test_case450(self): + """ + construct_lvs_nonexistent_bdev + + Negative test for constructing a new lvol store. + Call construct_lvol_store with base bdev name which does not + exist in configuration. + """ fail_count = 0 bad_bdev_id = random.randrange(999999999) + # Try construct_lvol_store on bdev which does not exist if self.c.construct_lvol_store(bad_bdev_id, self.lvs_name, self.cluster_size) == 0: @@ -696,12 +1114,23 @@ class TestCases(object): @case_message def test_case451(self): + """ + construct_lvs_on_bdev_twice + + Negative test for constructing a new lvol store. + Call construct_lvol_store with base bdev name twice. + """ + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Try construct_lvol_store on the same bdev as in last step + # This call should fail as base bdev is already claimed by lvol store if self.c.construct_lvol_store(base_name, self.lvs_name) == 0: fail_count += 1 @@ -711,16 +1140,30 @@ class TestCases(object): @case_message def test_case452(self): + """ + construct_lvs_name_twice + + Negative test for constructing a new lvol store using the same + friendly name twice. + """ fail_count = 0 + # Create malloc bdev base_name_1 = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct second malloc bdev base_name_2 = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on first malloc uuid_store_1 = self.c.construct_lvol_store(base_name_1, self.lvs_name) + # using get_lvol_stores verify that logical volume store was correctly created + # and has arguments as provided in step earlier (cluster size, friendly name, base bdev) fail_count += self.c.check_get_lvol_stores(base_name_1, uuid_store_1, self.cluster_size) + # Try to create another logical volume store on second malloc bdev using the + # same friendly name as before. This step is expected to fail as lvol stores + # cannot have the same name if self.c.construct_lvol_store(base_name_2, self.lvs_name) == 0: fail_count += 1 @@ -2433,21 +2876,28 @@ class TestCases(object): @case_message def test_case800(self): + """ + rename_positive + + Positive test for lvol store and lvol bdev rename. + """ fail_count = 0 bdev_uuids = [] bdev_names = [self.lbd_name + str(i) for i in range(4)] bdev_aliases = ["/".join([self.lvs_name, name]) for name in bdev_names] - # Create a lvol store with 4 lvol bdevs + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bdev lvs_uuid = self.c.construct_lvol_store(base_name, self.lvs_name) fail_count += self.c.check_get_lvol_stores(base_name, lvs_uuid, self.cluster_size, self.lvs_name) + # Create 4 lvol bdevs on top of previously created lvol store bdev_size = self.get_lvs_divided_size(4) for name, alias in zip(bdev_names, bdev_aliases): uuid = self.c.construct_lvol_bdev(lvs_uuid, @@ -2476,6 +2926,7 @@ class TestCases(object): alias) # Now try to rename the bdevs using their uuid as "old_name" + # Verify that all bdev names were successfully updated bdev_names = ["lbd_new" + str(i) for i in range(4)] bdev_aliases = ["/".join([new_lvs_name, name]) for name in bdev_names] print(bdev_aliases) @@ -2484,7 +2935,8 @@ class TestCases(object): fail_count += self.c.check_get_bdevs_methods(uuid, bdev_size, new_alias) - # Same thing but only use aliases + # Rename lvol bdevs. Use lvols alias name to point which lvol bdev name to change + # Verify that all bdev names were successfully updated bdev_names = ["lbd_even_newer" + str(i) for i in range(4)] new_bdev_aliases = ["/".join([new_lvs_name, name]) for name in bdev_names] print(bdev_aliases) @@ -2500,17 +2952,40 @@ class TestCases(object): fail_count += self.c.destroy_lvol_store(new_lvs_name) fail_count += self.c.delete_malloc_bdev(base_name) + # Expected results: + # - lvol store and lvol bdevs correctly created + # - lvol store and lvol bdevs names updated after renaming operation + # - lvol store and lvol bdevs possible to delete using new names + # - no other operation fails return fail_count @case_message def test_case801(self): + """ + rename_lvs_nonexistent + + Negative test case for lvol store rename. + Check that error is returned when trying to rename not existing lvol store. + """ fail_count = 0 + # Call rename_lvol_store with name pointing to not existing lvol store if self.c.rename_lvol_store("NOTEXIST", "WHATEVER") == 0: fail_count += 1 + + # Expected results: + # - rename_lvol_store return code != 0 + # - no other operation fails return fail_count @case_message def test_case802(self): + """ + rename_lvs_EEXIST + + Negative test case for lvol store rename. + Check that error is returned when trying to rename to a name which is already + used by another lvol store. + """ fail_count = 0 lvs_name_1 = "lvs_1" @@ -2524,6 +2999,7 @@ class TestCases(object): bdev_aliases_2 = ["/".join([lvs_name_2, name]) for name in bdev_names_2] bdev_uuids_2 = [] + # Construct two malloc bdevs base_bdev_1 = self.c.construct_malloc_bdev(self.total_size, self.block_size) base_bdev_2 = self.c.construct_malloc_bdev(self.total_size, @@ -2563,7 +3039,8 @@ class TestCases(object): alias) bdev_uuids_2.append(uuid) - # Try to rename lvol store to already existing name + # Call rename_lvol_store on first lvol store and try to change its name to + # the same name as used by second lvol store if self.c.rename_lvol_store(lvs_name_1, lvs_name_2) == 0: fail_count += 1 @@ -2595,27 +3072,53 @@ class TestCases(object): fail_count += self.c.delete_malloc_bdev(base_bdev_1) fail_count += self.c.delete_malloc_bdev(base_bdev_2) + # Expected results: + # - rename_lvol_store return code != 0; not possible to rename to already + # used name + # - no other operation fails + return fail_count @case_message def test_case803(self): + """ + rename_lvol_bdev_nonexistent + + Negative test case for lvol bdev rename. + Check that error is returned when trying to rename not existing lvol bdev. + """ fail_count = 0 + # Call rename_lvol_bdev with name pointing to not existing lvol bdev if self.c.rename_lvol_bdev("NOTEXIST", "WHATEVER") == 0: fail_count += 1 + + # Expected results: + # - rename_lvol_bdev return code != 0 + # - no other operation fails return fail_count @case_message def test_case804(self): + """ + rename_lvol_bdev_EEXIST + + Negative test case for lvol bdev rename. + Check that error is returned when trying to rename to a name which is already + used by another lvol bdev. + """ fail_count = 0 + # Construt malloc bdev base_bdev = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Create lvol store on created malloc bdev lvs_uuid = self.c.construct_lvol_store(base_bdev, self.lvs_name) fail_count += self.c.check_get_lvol_stores(base_bdev, lvs_uuid, self.cluster_size, self.lvs_name) + # Construct 2 lvol bdevs on lvol store bdev_size = self.get_lvs_divided_size(2) bdev_uuid_1 = self.c.construct_lvol_bdev(lvs_uuid, self.lbd_name + "1", @@ -2628,8 +3131,11 @@ class TestCases(object): fail_count += self.c.check_get_bdevs_methods(bdev_uuid_2, bdev_size) + # Call rename_lvol_bdev on first lvol bdev and try to change its name to + # the same name as used by second lvol bdev if self.c.rename_lvol_bdev(self.lbd_name + "1", self.lbd_name + "2") == 0: fail_count += 1 + # Verify that lvol bdev still have the same names as before fail_count += self.c.check_get_bdevs_methods(bdev_uuid_1, bdev_size, "/".join([self.lvs_name, self.lbd_name + "1"])) @@ -2639,18 +3145,35 @@ class TestCases(object): fail_count += self.c.destroy_lvol_store(lvs_uuid) fail_count += self.c.delete_malloc_bdev(base_bdev) + # Expected results: + # - rename_lvol_bdev return code != 0; not possible to rename to already + # used name + # - no other operation fails return fail_count @case_message def test_case10000(self): - pid_path = path.join(self.path, 'vhost.pid') + """ + SIGTERM + Call CTRL+C (SIGTERM) occurs after creating lvol store + """ + pid_path = path.join(self.path, 'vhost.pid') + # Create malloc bdev base_name = self.c.construct_malloc_bdev(self.total_size, self.block_size) + # Construct lvol store on created malloc bddev uuid_store = self.c.construct_lvol_store(base_name, self.lvs_name) + # Check correct uuid values in response get_lvol_stores command fail_count = self.c.check_get_lvol_stores(base_name, uuid_store, self.cluster_size) + # Send SIGTERM signal to the application fail_count += self._stop_vhost(pid_path) + + # Expected result: + # - calls successful, return code = 0 + # - get_bdevs: no change + # - no other operation fails return fail_count diff --git a/test/lvol/test_plan.md b/test/lvol/test_plan.md deleted file mode 100644 index 5e38699a6..000000000 --- a/test/lvol/test_plan.md +++ /dev/null @@ -1,585 +0,0 @@ -# Lvol feature test plan - -## Objective -The purpose of these tests is to verify the possibility of using lvol configuration in SPDK. - -## Methodology -Configuration in test is to be done using example stub application. -All management is done using RPC calls, including logical volumes management. -All tests are performed using malloc backends. -One exception to malloc backends are tests for logical volume -tasting - these require persistent merory like NVMe backend. - -Tests will be executed as scenarios - sets of smaller test step -in which return codes from RPC calls is validated. -Some configuration calls may also be validated by use of -"get_*" RPC calls, which provide additional information for verifying -results. - -Tests with thin provisioned lvol bdevs, snapshots and clones are using nbd devices. -Before writing/reading to lvol bdev, bdev is installed with rpc start_nbd_disk. -After finishing writing/reading, rpc stop_nbd_disk is used. - -## Tests - -### construct_lvol_store - positive tests - -#### TEST CASE 1 - Name: construct_lvs_positive -Positive test for constructing a new lvol store. -Call construct_lvol_store with correct base bdev name. -Steps: -- create a malloc bdev -- construct_lvol_store on correct, exisitng malloc bdev -- check correct uuid values in response get_lvol_stores command -- destroy lvol store -- delete malloc bdev - -Expected result: -- call successful, return code = 0, uuid printed to stdout -- get_lvol_stores: backend used for construct_lvol_store has uuid - field set with the same uuid as returned from RPC call -- no other operation fails - -### construct_lvol_bdev - positive tests - -#### TEST CASE 50 - Name: construct_logical_volume_positive -Positive test for constructing a new logical volume. -Call construct_lvol_bdev with correct lvol store UUID and size in MiB for this bdev. -Steps: -- create a malloc bdev -- construct_lvol_store on correct, exisitng malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size -- delete lvol bdev -- destroy lvol store -- delete malloc bdev - -Expected result: -- call successful, return code = 0 -- get_bdevs: backend used for construct_lvol_bdev has name - field set with the same name as returned value from call RPC method: construct_lvol_bdev -- no other operation fails - -#### TEST CASE 51 - Name: construct_multi_logical_volumes_positive -Positive test for constructing a multi logical volumes. -Call construct_lvol_bdev with correct lvol store UUID and -size is equal one quarter of the this bdev size. -Steps: -- create a malloc bdev -- construct_lvol_store on correct, exisitng malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size - (size is approximately equal to one quarter of the bdev size, - because of lvol metadata) -- repeat the previous step three more times -- delete lvol bdevs -- create and delete four lvol bdevs again from steps above -- destroy lvol store -- delete malloc bdev - -Expected result: -- call successful, return code = 0 -- get_lvol_store: backend used for construct_lvol_bdev has name - field set with the same name as returned from RPC call for all repeat -- no other operation fails - -#### TEST CASE 52 - Name: construct_lvol_bdev_using_name_positive -Positive test for constructing a logical volume using friendly names. -Verify that logical volumes can be created by using a friendly name -instead of uuid when referencing to lvol store. -Steps: -- create malloc bdev -- create logical volume store on created malloc bdev -- verify lvol store was created correctly -- create logical volume on lvol store by using a friendly name - as a reference -- verify logical volume was correctly created -- delete logical volume bdev -- destroy logical volume store -- delete malloc bdev - -Expected result: -- calls successful, return code = 0 -- no other operation fails - -#### TEST CASE 53 - Name: construct_lvol_bdev_duplicate_names_positive -Positive test for constructing a logical volumes using friendly names. -Verify that logical volumes can use the same argument for friendly names -if they are created on separate logical volume stores. -Steps: -- create two malloc bdevs -- create logical volume stores on created malloc bdevs -- verify stores were created correctly -- create logical volume on first lvol store -- verify it was correctly created -- using the same friendly name argument create logical volume on second - lvol store -- verify logical volume was correctly created -- delete logical volume bdevs -- destroy logical volume stores -- delete malloc bdevs - -Expected result: -- calls successful, return code = 0 -- no other operation fails - -### construct_lvol_bdev - negative tests - -#### TEST CASE 100 - Name: construct_logical_volume_nonexistent_lvs_uuid -Negative test for constructing a new logical_volume. -Call construct_lvol_bdev with lvs_uuid which does not -exist in configuration. -Steps: -- try to call construct_lvol_bdev with lvs_uuid which does not exist - -Expected result: -- return code != 0 -- ENODEV response printed to stdout - -#### TEST CASE 101 - Name: construct_lvol_bdev_on_full_lvol_store -Negative test for constructing a new lvol bdev. -Call construct_lvol_bdev on a full lvol store. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response from get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is smaller by 1 MB - from the full size malloc bdev -- try construct_lvol_bdev on the same lvs_uuid as in last step; - this call should fail as lvol store space is taken by previously created bdev -- destroy_lvol_store -- delete malloc bdev - -Expected result: -- first call successful -- second construct_lvol_bdev call return code != 0 -- EEXIST response printed to stdout -- no other operation fails - -#### TEST CASE 102 - Name: construct_lvol_bdev_name_twice -Negative test for constructing lvol bdev using the same -friendly name twice on the same logical volume store. -Steps: -- create malloc bdev -- create logical volume store on malloc bdev -- using get_lvol_stores verify that logical volume store was correctly created - and has arguments as provided in step earlier (cluster size, friendly name, base bdev) -- construct logical volume on lvol store and verify it was correctly created -- try to create another logical volume on the same lvol store using -the same friendly name as in previous step; this step should fail -- delete existing lvol bdev -- delete existing lvol store -- delete malloc bdevs - -Expected results: -- creating two logical volumes with the same friendly name within the same - lvol store should not be possible -- no other operation fails - -### resize_lvol_store - positive tests - -#### TEST CASE 150 - Name: resize_logical_volume_positive -Positive test for resizing a logical_volume. -Call resize_lvol_bdev with correct logical_volumes name and new size. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is - equal to one quarter of size malloc bdev -- check size of the lvol bdev by command RPC : get_bdevs -- resize_lvol_bdev on correct lvs_uuid and size is - equal half to size malloc bdev -- check size of the lvol bdev by command RPC : get_bdevs -- resize_lvol_bdev on the correct lvs_uuid and size is smaller by 1 MB - from the full size malloc bdev -- check size of the lvol bdev by command RPC : get_bdevs -- resize_lvol_bdev on the correct lvs_uuid and size is equal 0 MiB -- check size of the lvol bdev by command RPC : get_bdevs -- delete lvol bdev -- destroy lvol store -- delete malloc bdev - -Expected result: -- lvol bdev should change size after resize operations -- calls successful, return code = 0 -- no other operation fails - -### resize lvol store - negative tests - -#### TEST CASE 200 - Name: resize_logical_volume_nonexistent_logical_volume -Negative test for resizing a logical_volume. -Call resize_lvol_bdev with logical volume which does not -exist in configuration. -Steps: -- try resize_lvol_store on logical volume which does not exist - -Expected result: -- return code != 0 -- Error code: ENODEV ("No such device") response printed to stdout - -#### TEST CASE 201 - Name: resize_logical_volume_with_size_out_of_range -Negative test for resizing a logical volume. -Call resize_lvol_store with size argument bigger than size of base bdev. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and - size is equal one quarter of size malloc bdev -- try resize_lvol_bdev on correct lvs_uuid and size is - equal to size malloc bdev + 1MiB; this call should fail -- delete lvol bdev -- destroy lvol store -- delete malloc bdev - -Expected result: -- resize_lvol_bdev call return code != 0 -- Error code: ENODEV ("Not enough free clusters left on lvol store") - response printed to stdout -- no other operation fails - -### destroy_lvol_store - positive tests - -#### TEST CASE 250 - Name: destroy_lvol_store_positive -Positive test for destroying a logical volume store. -Call destroy_lvol_store with correct logical_volumes name -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- destroy_lvol_store -- check correct response get_lvol_stores command -- delete malloc bdev - -Expected result: -- calls successful, return code = 0 -- get_lvol_stores: response should be of no value after destroyed lvol store -- no other operation fails - -#### TEST CASE 251 - Name: destroy_lvol_store_use_name_positive -Positive test for destroying a logical volume store using -lvol store name instead of uuid for reference. -Call destroy_lvol_store with correct logical volume name -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response from get_lvol_stores command -- destroy_lvol_store -- check correct response from get_lvol_stores command -- delete malloc bdev - -Expected result: -- calls successful, return code = 0 -- get_lvol_stores: response should be of no value after destroyed lvol store -- no other operation fails - -#### TEST CASE 252 - Name: destroy_lvol_store_with_lvol_bdev_positive -Positive test for destroying a logical volume store with lvol bdev -created on top. -Call destroy_lvol_store with correct logical_volumes name -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is equal to size malloc bdev -- destroy_lvol_store -- check correct response get_lvol_stores command -- delete malloc bdev - -Expected result: -- calls successful, return code = 0 -- get_lvol_stores: response should be of no value after destroyed lvol store -- no other operation fails - -#### TEST CASE 253 - Name: destroy_multi_logical_volumes_positive -Positive test for destroying a logical volume store with multiple lvol -bdevs created on top. -Call construct_lvol_bdev with correct lvol store UUID and -size is equal to one quarter of the this bdev size. -Steps: -- create a malloc bdev -- construct_lvol_store on correct, exisitng malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size - (size is equal to one quarter of the bdev size) -- repeat the previous step four times -- destroy_lvol_store -- check correct response get_lvol_stores command -- delete malloc bdev - -Expected result: -- call successful, return code = 0 -- get_lvol_store: backend used for construct_lvol_bdev has name - field set with the same name as returned from RPC call for all repeat -- no other operation fails - -#### TEST CASE 254 - Name: destroy_resize_logical_volume_positive -Positive test for destroying a logical_volume after resizing. -Call destroy_lvol_store with correct logical_volumes name. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is - equal to one quarter of size malloc bdev -- check size of the lvol bdev -- resize_lvol_bdev on correct lvs_uuid and size is - equal half of size malloc bdev -- check size of the lvol bdev by command RPC : get_bdevs -- Resize_lvol_bdev on the correct lvs_uuid and the size is smaller by 1 MB - from the full size malloc bdev -- check size of the lvol bdev by command RPC : get_bdevs -- resize_lvol_bdev on the correct lvs_uuid and size is equal 0 MiB -- check size of the lvol bdev by command RPC : get_bdevs -- destroy_lvol_store -- delete malloc bdev - -Expected result: -- lvol bdev should change size after resize operations -- calls successful, return code = 0 -- no other operation fails -- get_lvol_stores: response should be of no value after destroyed lvol store - -#### TEST CASE 255 - Name: delete_lvol_store_persistent_positive -Positive test for removing lvol store persistently -Steps: -- construct_lvol_store on NVMe bdev -- destroy lvol store -- delete NVMe bdev -- add NVMe bdev -- check if destroyed lvol store does not exist on NVMe bdev - -Expected result: -- get_lvol_stores should not report any existsing lvol stores in configuration - after deleting and adding NVMe bdev -- no other operation fails - -### destroy_lvol_store - negative tests - -#### TEST CASE 300 - Name: destroy_lvol_store_nonexistent_lvs_uuid -Call destroy_lvol_store with nonexistent logical_volumes name -exist in configuration. -Steps: -- try to call destroy_lvol_store with lvs_uuid which does not exist - -Expected result: -- return code != 0 -- Error code response printed to stdout - -#### TEST CASE 301 - Name: delete_lvol_store_underlying_bdev -Call destroy_lvol_store after deleting it's base bdev. -Lvol store should be automatically removed on deleting underlying bdev. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- delete malloc bdev -- try to destroy lvol store; this call should fail as lvol store - is no longer present - -Expected result: -- destroy_lvol_store retudn code != 0 -- Error code: ENODEV ("No such device") response printed to stdout -- no other operation fails - -### nested destroy_lvol_bdev - negative tests - -#### TEST CASE 350 - Name: nested_destroy_logical_volume_negative -Negative test for destroying a nested first lvol store. -Call destroy_lvol_store with correct base bdev name. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is - equal to size malloc bdev -- construct first nested lvol store on created lvol_bdev -- check correct uuid values in response get_lvol_stores command -- construct first nested lvol bdev on correct lvs_uuid and size -- check size of the lvol bdev by command RPC : get_bdevs -- destroy first lvol_store -- delete malloc bdev - -Expected result: -- Error code: ENODEV ("the device is busy") response printed to stdout -- no other operation fails - -### nested construct_logical_volume - positive tests - -#### TEST CASE 400 - Name: nested_construct_logical_volume_positive -Positive test for constructing a nested new lvol store. -Call construct_lvol_store with correct base bdev name. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- construct_lvol_bdev on correct lvs_uuid and size is - equal to size malloc bdev -- construct first nested lvol store on created lvol_bdev -- check correct uuid values in response get_lvol_stores command -- construct first nested lvol bdev on correct lvs_uuid and size -- construct second nested lvol store on created first nested lvol bdev -- check correct uuid values in response get_lvol_stores command -- construct second nested lvol bdev on correct first nested lvs uuid and size -- delete nested lvol bdev and lvol store -- delete base lvol bdev and lvol store -- delete malloc bdev - -Expected result: -- calls successful, return code = 0 -- get_lvol_stores: backend used for construct_lvol_store has UUID - field set with the same UUID as returned from RPC call - backend used for construct_lvol_bdev has UUID - field set with the same UUID as returned from RPC call -- no other operation fails - -### construct_lvol_store - negative tests - -#### TEST CASE 450 - Name: construct_lvs_nonexistent_bdev -Negative test for constructing a new lvol store. -Call construct_lvol_store with base bdev name which does not -exist in configuration. -Steps: -- try construct_lvol_store on bdev which does not exist - -Expected result: -- return code != 0 -- Error code: ENODEV ("No such device") response printed to stdout - -#### TEST CASE 451 - Name: construct_lvs_on_bdev_twice -Negative test for constructing a new lvol store. -Call construct_lvol_store with base bdev name twice. -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- try construct_lvol_store on the same bdev as in last step; - this call should fail as base bdev is already claimed by lvol store -- destroy lvs -- delete malloc bdev - -Expected result: -- first call successful -- second construct_lvol_store call return code != 0 -- EEXIST response printed to stdout -- no other operation fails - -#### TEST CASE 452 - Name: construct_lvs_name_twice -Negative test for constructing a new lvol store using the same -friendly name twice. -Steps: -- create two malloc bdevs -- create logical volume store on first malloc bdev -- using get_lvol_stores verify that logical volume store was correctly created - and has arguments as provided in step earlier (cluster size, friendly name, base bdev) -- try to create another logical volume store on second malloc bdev using the - same friendly name as before; this step is expected to fail as lvol stores - cannot have the same name -- delete existing lvol store -- delete malloc bdevs - -Expected results: -- creating two logical volume stores with the same friendly name should -not be possible -- no other operation fails - -### logical volume rename tests - -#### TEST CASE 800 - Name: rename_positive -Positive test for lvol store and lvol bdev rename. -Steps: -- create malloc bdev -- construct lvol store on malloc bdev -- create 4 lvol bdevs on top of previously created lvol store -- rename lvol store; verify that lvol store friendly name was - updated in get_lvol_stores output; verify that prefix in lvol bdevs - friendly names were also updated -- rename lvol bdevs; use lvols UUID's to point which lvol bdev name to change; - verify that all bdev names were successfully updated -- rename lvol bdevs; use lvols alias name to point which lvol bdev - name to change; verify that all bdev names were successfully updated -- clean running configuration: delete lvol bdevs, destroy lvol store, - delete malloc bdev; use lvol store and lvol bdev friendly names for delete - and destroy commands to check if new names can be correctly used for performing - other RPC operations; - -Expected results: -- lvol store and lvol bdevs correctly created -- lvol store and lvol bdevs names updated after renaming operation -- lvol store and lvol bdevs possible to delete using new names -- no other operation fails - -#### TEST CASE 801 - Name: rename_lvs_nonexistent -Negative test case for lvol store rename. -Check that error is returned when trying to rename not existing lvol store. - -Steps: -- call rename_lvol_store with name pointing to not existing lvol store - -Expected results: -- rename_lvol_store return code != 0 -- no other operation fails - -#### TEST CASE 802 - Name: rename_lvs_EEXIST -Negative test case for lvol store rename. -Check that error is returned when trying to rename to a name which is already -used by another lvol store. - -Steps: -- create 2 malloc bdevs -- construct lvol store on each malloc bdev -- on each lvol store create 4 lvol bdevs -- call rename_lvol_store on first lvol store and try to change its name to - the same name as used by second lvol store -- verify that both lvol stores still have the same names as before -- verify that lvol bdev have the same aliases as before - -Expected results: -- rename_lvol_store return code != 0; not possible to rename to already - used name -- no other operation fails - -#### TEST CASE 803 - Name: rename_lvol_bdev_nonexistent -Negative test case for lvol bdev rename. -Check that error is returned when trying to rename not existing lvol bdev. - -Steps: -- call rename_lvol_bdev with name pointing to not existing lvol bdev - -Expected results: -- rename_lvol_bdev return code != 0 -- no other operation fails - -#### TEST CASE 804 - Name: rename_lvol_bdev_EEXIST -Negative test case for lvol bdev rename. -Check that error is returned when trying to rename to a name which is already -used by another lvol bdev. - -Steps: -- create malloc bdev -- construct lvol store on malloc bdev -- construct 2 lvol bdevs on lvol store -- call rename_lvol_bdev on first lvol bdev and try to change its name to - the same name as used by second lvol bdev -- verify that both lvol bdev still have the same names as before - -Expected results: -- rename_lvol_bdev return code != 0; not possible to rename to already - used name -- no other operation fails - -### SIGTERM - -#### TEST CASE 10000 - Name: SIGTERM -Call CTRL+C (SIGTERM) occurs after creating lvol store -Steps: -- create a malloc bdev -- construct_lvol_store on created malloc bdev -- check correct uuid values in response get_lvol_stores command -- Send SIGTERM signal to the application - -Expected result: -- calls successful, return code = 0 -- get_bdevs: no change -- no other operation fails