test/lvol: Snapshot and clone test cases for lvol feature.

Also move snapshot and clone test plan into implementation.

Change-Id: Ifa1f2da651305747ae24c50921deebd0266c5888
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com>
Reviewed-on: https://review.gerrithub.io/392371
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Tomasz Kulasek 2018-03-08 23:09:32 +01:00 committed by Daniel Verkamp
parent 9b5fd19225
commit ebf079362b
4 changed files with 398 additions and 1 deletions

View File

@ -193,7 +193,7 @@ if [ $SPDK_TEST_LVOL -eq 1 ]; then
timing_enter lvol
test_cases="1,50,51,52,53,100,101,102,150,200,201,250,251,252,253,254,255,"
test_cases+="300,301,450,451,452,550,600,601,650,651,652,654,655,"
test_cases+="700,701,800,801,802,803,804,10000"
test_cases+="700,701,750,751,752,753,754,755,800,801,802,803,804,10000"
run_test ./test/lvol/lvol.sh --test-cases=$test_cases
report_test_completion "lvol"
timing_exit lvol

View File

@ -58,6 +58,12 @@ function usage() {
655: 'thin_provisioning_filling_disks_less_than_lvs_size',
700: 'tasting_positive',
701: 'tasting_lvol_store_positive',
750: 'snapshot_readonly',
751: 'snapshot_compare_with_lvol_bdev',
752: 'snapshot_during_io_traffic',
753: 'snapshot_of_snapshot',
754: 'clone_bdev_only',
755: 'clone_writing_clone',
800: 'rename_positive',
801: 'rename_lvs_nonexistent',
802: 'rename_lvs_EEXIST',

View File

@ -200,3 +200,13 @@ class Commands_Rpc(object):
print("INFO: Renaming lvol bdev from {old} to {new}".format(old=old_name, new=new_name))
output, rc = self.rpc.rename_lvol_bdev(old_name, new_name)
return rc
def snapshot_lvol_bdev(self, bdev_name, snapshot_name):
print("INFO: RPC COMMAND snapshot_lvol_bdev")
output, rc = self.rpc.snapshot_lvol_bdev(bdev_name, snapshot_name)
return rc
def clone_lvol_bdev(self, snapshot_name, clone_name):
print("INFO: RPC COMMAND clone_lvol_bdev")
output, rc = self.rpc.clone_lvol_bdev(snapshot_name, clone_name)
return rc

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python
import io
import time
import sys
import random
import signal
@ -7,6 +8,7 @@ import subprocess
import pprint
import socket
import threading
import os
from errno import ESRCH
from os import kill, path, unlink, path, listdir, remove
@ -125,6 +127,12 @@ def case_message(func):
655: 'thin_provisioning_filling_disks_less_than_lvs_size',
700: 'tasting_positive',
701: 'tasting_lvol_store_positive',
750: 'snapshot_readonly',
751: 'snapshot_compare_with_lvol_bdev',
752: 'snapshot_during_io_traffic',
753: 'snapshot_of_snapshot',
754: 'clone_bdev_only',
755: 'clone_writing_clone',
800: 'rename_positive',
801: 'rename_lvs_nonexistent',
802: 'rename_lvs_EEXIST',
@ -1235,6 +1243,379 @@ class TestCases(object):
fail_count += 1
return fail_count
@case_message
def test_case750(self):
"""
snapshot readonly
Create snaphot of lvol bdev and check if it is readonly.
"""
fail_count = 0
nbd_name0 = "/dev/nbd0"
snapshot_name = "snapshot0"
# Construct malloc bdev
base_name = self.c.construct_malloc_bdev(self.total_size,
self.block_size)
# Construct lvol store on malloc bdev
uuid_store = self.c.construct_lvol_store(base_name,
self.lvs_name,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()[0]
free_clusters_start = int(lvs['free_clusters'])
bdev_size = int(int(lvs['cluster_size']) * int(lvs['free_clusters']) / MEGABYTE / 3)
# Create lvol bdev with 33% of lvol store space
bdev_name = self.c.construct_lvol_bdev(uuid_store, self.lbd_name,
bdev_size)
lvol_bdev = self.c.get_lvol_bdev_with_name(bdev_name)
# Create snapshot of lvol bdev
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name)
snapshot_bdev = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + snapshot_name)
fail_count += self.c.start_nbd_disk(snapshot_bdev['name'], nbd_name0)
size = bdev_size * MEGABYTE
# Try to perform write operation on created snapshot
# Check if filling snapshot of lvol bdev fails
fail_count += self.run_fio_test(nbd_name0, 0, size, "write", "0xcc", 1)
fail_count += self.c.stop_nbd_disk(nbd_name0)
# Destroy lvol bdev
fail_count += self.c.delete_bdev(lvol_bdev['name'])
# Destroy snapshot
fail_count += self.c.delete_bdev(snapshot_bdev['name'])
# Destroy lvol store
fail_count += self.c.destroy_lvol_store(uuid_store)
# Delete malloc bdev
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - no other operation fails
return fail_count
@case_message
def test_case751(self):
"""
snapshot_compare_with_lvol_bdev
Check if lvol bdevs and snapshots contain the same data.
Check if lvol bdev and snapshot differ when writing to lvol bdev
after creating snapshot.
"""
fail_count = 0
nbd_name = ["/dev/nbd0", "/dev/nbd1", "/dev/nbd2", "/dev/nbd3"]
snapshot_name0 = "snapshot0"
snapshot_name1 = "snapshot1"
# Construct mallov 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,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()
size = int(int(lvs[0][u'free_clusters'] * lvs[0]['cluster_size']) / 6 / MEGABYTE)
lbd_name0 = self.lbd_name + str(0)
lbd_name1 = self.lbd_name + str(1)
# Create thin provisioned lvol bdev with size less than 25% of lvs
uuid_bdev0 = self.c.construct_lvol_bdev(uuid_store,
lbd_name0, size, thin=True)
# Create thick provisioned lvol bdev with size less than 25% of lvs
uuid_bdev1 = self.c.construct_lvol_bdev(uuid_store,
lbd_name1, size, thin=False)
lvol_bdev0 = self.c.get_lvol_bdev_with_name(uuid_bdev0)
fail_count += self.c.start_nbd_disk(lvol_bdev0['name'], nbd_name[0])
fill_size = int(size * MEGABYTE / 2)
# Fill thin provisoned lvol bdev with 50% of its space
fail_count += self.run_fio_test(nbd_name[0], 0, fill_size, "write", "0xcc", 0)
lvol_bdev1 = self.c.get_lvol_bdev_with_name(uuid_bdev1)
fail_count += self.c.start_nbd_disk(lvol_bdev1['name'], nbd_name[1])
fill_size = int(size * MEGABYTE)
# Fill whole thic provisioned lvol bdev
fail_count += self.run_fio_test(nbd_name[1], 0, fill_size, "write", "0xcc", 0)
# Create snapshots of lvol bdevs
fail_count += self.c.snapshot_lvol_bdev(uuid_bdev0, snapshot_name0)
fail_count += self.c.snapshot_lvol_bdev(uuid_bdev1, snapshot_name1)
fail_count += self.c.start_nbd_disk(self.lvs_name + "/" + snapshot_name0, nbd_name[2])
fail_count += self.c.start_nbd_disk(self.lvs_name + "/" + snapshot_name1, nbd_name[3])
# Compare every lvol bdev with corresponding snapshot
# and check that data are the same
fail_count += self.compare_two_disks(nbd_name[0], nbd_name[2], 0)
fail_count += self.compare_two_disks(nbd_name[1], nbd_name[3], 0)
fill_size = int(size * MEGABYTE / 2)
offset = fill_size
# Fill second half of thin provisioned lvol bdev
fail_count += self.run_fio_test(nbd_name[0], offset, fill_size, "write", "0xaa", 0)
# Compare thin provisioned lvol bdev with its snapshot and check if it fails
fail_count += self.compare_two_disks(nbd_name[0], nbd_name[2], 1)
for nbd in nbd_name:
fail_count += self.c.stop_nbd_disk(nbd)
# Delete lvol bdevs
fail_count += self.c.delete_bdev(lvol_bdev0['name'])
fail_count += self.c.delete_bdev(lvol_bdev1['name'])
# Delete snapshots
fail_count += self.c.delete_bdev(self.lvs_name + "/" + snapshot_name0)
fail_count += self.c.delete_bdev(self.lvs_name + "/" + snapshot_name1)
# Destroy snapshot
fail_count += self.c.destroy_lvol_store(uuid_store)
# Delete malloc bdev
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - removing snapshot should always end with success
# - no other operation fails
return fail_count
@case_message
def test_case752(self):
"""
snapshot_during_io_traffic
Check that when writing to lvol bdev
creating snapshot ends with success
"""
global current_fio_pid
fail_count = 0
nbd_name = "/dev/nbd0"
snapshot_name = "snapshot"
# 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,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()
# Create thin provisioned lvol bdev with size equal to 50% of lvs space
size = int(int(lvs[0][u'free_clusters'] * lvs[0]['cluster_size']) / 2 / MEGABYTE)
uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name,
size, thin=True)
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev)
fail_count += self.c.start_nbd_disk(lvol_bdev['name'], nbd_name)
fill_size = int(size * MEGABYTE)
# Create thread that will run fio in background
thread = FioThread(nbd_name, 0, fill_size, "write", "0xcc", 0,
extra_params="--time_based --runtime=8")
# Perform write operation with verification to created lvol bdev
thread.start()
time.sleep(4)
fail_count += is_process_alive(current_fio_pid)
# During write operation create snapshot of created lvol bdev
# and check that snapshot has been created successfully
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name)
fail_count += is_process_alive(current_fio_pid)
thread.join()
# Check that write operation ended with success
fail_count += thread.rv
fail_count += self.c.stop_nbd_disk(nbd_name)
# Destroy lvol bdev
fail_count += self.c.delete_bdev(lvol_bdev['name'])
# Delete snapshot
fail_count += self.c.delete_bdev(self.lvs_name + "/" + snapshot_name)
# Destroy lvol store
fail_count += self.c.destroy_lvol_store(uuid_store)
# Delete malloc bdevs
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - no other operation fails
return fail_count
@case_message
def test_case753(self):
"""
snapshot_of_snapshot
Check that creating snapshot of snapshot will fail
"""
fail_count = 0
snapshot_name0 = "snapshot0"
snapshot_name1 = "snapshot1"
# 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,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()
# Create thick provisioned lvol bdev
size = int(int(lvs[0][u'free_clusters'] * lvs[0]['cluster_size']) / 2 / MEGABYTE)
uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name,
size, thin=False)
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev)
# Create snapshot of created lvol bdev
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name0)
# Create snapshot of previously created snapshot
# and check if operation will fail
if self.c.snapshot_lvol_bdev(snapshot_name0, snapshot_name1) == 0:
print("ERROR: Creating snapshot of snapshot should fail")
fail_count += 1
# Delete lvol bdev
fail_count += self.c.delete_bdev(lvol_bdev['name'])
# Destroy snapshot
fail_count += self.c.delete_bdev(self.lvs_name + "/" + snapshot_name0)
# Destroy lvol store
fail_count += self.c.destroy_lvol_store(uuid_store)
# Delete malloc bdev
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - creating snapshot of snapshot should fail
# - no other operation fails
return fail_count
@case_message
def test_case754(self):
"""
clone_bdev_only
Check that only clone of snapshot can be created.
Creating clone of lvol bdev should fail.
"""
fail_count = 0
clone_name = "clone"
snapshot_name = "snapshot"
# 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,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()
# Create thick provisioned lvol bdev with size equal to 50% of lvs space
size = int(int(lvs[0][u'free_clusters'] * lvs[0]['cluster_size']) / 2 / MEGABYTE)
uuid_bdev = self.c.construct_lvol_bdev(uuid_store, self.lbd_name,
size, thin=False)
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev)
# Create clone of lvol bdev and check if it fails
rv = self.c.clone_lvol_bdev(lvol_bdev['name'], clone_name)
if rv == 0:
print("ERROR: Creating clone of lvol bdev ended with unexpected success")
fail_count += 1
# Create snapshot of lvol bdev
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name)
# Create again clone of lvol bdev and check if it fails
rv = self.c.clone_lvol_bdev(lvol_bdev['name'], clone_name)
if rv == 0:
print("ERROR: Creating clone of lvol bdev ended with unexpected success")
fail_count += 1
# Create clone of snapshot and check if it ends with success
rv = self.c.clone_lvol_bdev(self.lvs_name + "/" + snapshot_name, clone_name)
if rv != 0:
print("ERROR: Creating clone of snapshot ended with unexpected failure")
fail_count += 1
clone_bdev = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + clone_name)
# Delete lvol bdev
fail_count += self.c.delete_bdev(lvol_bdev['name'])
# Destroy clone
fail_count += self.c.delete_bdev(clone_bdev['name'])
# Delete snapshot
fail_count += self.c.delete_bdev(self.lvs_name + "/" + snapshot_name)
# Delete lvol store
fail_count += self.c.destroy_lvol_store(uuid_store)
# Destroy malloc bdev
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - cloning thick provisioned lvol bdev should fail
# - no other operation fails
return fail_count
@case_message
def test_case755(self):
"""
clone_writing_to_clone
"""
fail_count = 0
nbd_name = ["/dev/nbd0", "/dev/nbd1", "/dev/nbd2", "/dev/nbd3"]
snapshot_name = "snapshot"
clone_name0 = "clone0"
clone_name1 = "clone1"
# Create 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,
self.cluster_size)
fail_count += self.c.check_get_lvol_stores(base_name, uuid_store,
self.cluster_size)
lvs = self.c.get_lvol_stores()
size = int(int(lvs[0][u'free_clusters'] * lvs[0]['cluster_size']) / 6 / MEGABYTE)
lbd_name0 = self.lbd_name + str(0)
# Construct thick provisioned lvol bdev
uuid_bdev0 = self.c.construct_lvol_bdev(uuid_store,
lbd_name0, size, thin=False)
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev0)
# Install lvol bdev on /dev/nbd0
fail_count += self.c.start_nbd_disk(lvol_bdev['name'], nbd_name[0])
fill_size = size * MEGABYTE
# Fill lvol bdev with 100% of its space
fail_count += self.run_fio_test(nbd_name[0], 0, fill_size, "write", "0xcc", 0)
# Create snapshot of thick provisioned lvol bdev
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name)
snapshot_bdev = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + snapshot_name)
# Create two clones of created snapshot
fail_count += self.c.clone_lvol_bdev(snapshot_bdev['name'], clone_name0)
fail_count += self.c.clone_lvol_bdev(snapshot_bdev['name'], clone_name1)
lvol_clone0 = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + clone_name0)
fail_count += self.c.start_nbd_disk(lvol_clone0['name'], nbd_name[1])
fill_size = int(size * MEGABYTE / 2)
# Perform write operation to first clone
# Change first half of its space
fail_count += self.run_fio_test(nbd_name[1], 0, fill_size, "write", "0xaa", 0)
fail_count += self.c.start_nbd_disk(self.lvs_name + "/" + snapshot_name, nbd_name[2])
lvol_clone1 = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + clone_name1)
fail_count += self.c.start_nbd_disk(lvol_clone1['name'], nbd_name[3])
# Compare snapshot with second clone. Data on both bdevs should be the same
time.sleep(1)
fail_count += self.compare_two_disks(nbd_name[2], nbd_name[3], 0)
for nbd in nbd_name:
fail_count += self.c.stop_nbd_disk(nbd)
# Destroy lvol bdev
fail_count += self.c.delete_bdev(lvol_bdev['name'])
# Destroy two clones
fail_count += self.c.delete_bdev(lvol_clone0['name'])
fail_count += self.c.delete_bdev(lvol_clone1['name'])
# Delete snapshot
fail_count += self.c.delete_bdev(snapshot_bdev['name'])
# Destroy lvol store
fail_count += self.c.destroy_lvol_store(uuid_store)
# Delete malloc
fail_count += self.c.delete_bdev(base_name)
# Expected result:
# - calls successful, return code = 0
# - no other operation fails
return fail_count
@case_message
def test_case800(self):
fail_count = 0