forked from TrueCloudLab/frostfs-testcases
Refactor for cluster usage
Signed-off-by: Andrey Berezin <a.berezin@yadro.com>
This commit is contained in:
parent
d9e881001e
commit
bd05aae585
46 changed files with 3859 additions and 2703 deletions
|
@ -3,6 +3,8 @@ import re
|
|||
|
||||
import allure
|
||||
import pytest
|
||||
from cluster import Cluster
|
||||
from cluster_test_base import ClusterTestBase
|
||||
from common import COMPLEX_OBJ_SIZE, SIMPLE_OBJ_SIZE, STORAGE_GC_TIME
|
||||
from complex_object_actions import get_link_object
|
||||
from container import create_container
|
||||
|
@ -22,9 +24,11 @@ from python_keywords.neofs_verbs import delete_object, head_object, lock_object
|
|||
from test_control import expect_not_raises, wait_for_success
|
||||
from utility import parse_time, wait_for_gc_pass_on_storage_nodes
|
||||
|
||||
import steps
|
||||
from helpers.container import StorageContainer, StorageContainerInfo
|
||||
from helpers.storage_object_info import LockObjectInfo, StorageObjectInfo
|
||||
from helpers.wallet import WalletFactory, WalletFile
|
||||
from steps.cluster_test_base import ClusterTestBase
|
||||
from steps.storage_object import delete_objects
|
||||
|
||||
logger = logging.getLogger("NeoLogger")
|
||||
|
@ -33,25 +37,6 @@ FIXTURE_LOCK_LIFETIME = 5
|
|||
FIXTURE_OBJECT_LIFETIME = 10
|
||||
|
||||
|
||||
def get_storage_object_chunks(storage_object: StorageObjectInfo, shell: Shell):
|
||||
with allure.step(f"Get complex object chunks (f{storage_object.oid})"):
|
||||
split_object_id = get_link_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
shell,
|
||||
is_direct=False,
|
||||
)
|
||||
head = head_object(
|
||||
storage_object.wallet_file_path, storage_object.cid, split_object_id, shell
|
||||
)
|
||||
|
||||
chunks_object_ids = []
|
||||
if "split" in head["header"] and "children" in head["header"]["split"]:
|
||||
chunks_object_ids = head["header"]["split"]["children"]
|
||||
return chunks_object_ids
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
scope="module",
|
||||
)
|
||||
|
@ -64,9 +49,11 @@ def user_wallet(wallet_factory: WalletFactory):
|
|||
@pytest.fixture(
|
||||
scope="module",
|
||||
)
|
||||
def user_container(user_wallet: WalletFile, client_shell: Shell):
|
||||
container_id = create_container(user_wallet.path, shell=client_shell)
|
||||
return StorageContainer(StorageContainerInfo(container_id, user_wallet), client_shell)
|
||||
def user_container(user_wallet: WalletFile, client_shell: Shell, cluster: Cluster):
|
||||
container_id = create_container(
|
||||
user_wallet.path, shell=client_shell, endpoint=cluster.default_rpc_endpoint
|
||||
)
|
||||
return StorageContainer(StorageContainerInfo(container_id, user_wallet), client_shell, cluster)
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
|
@ -75,10 +62,11 @@ def user_container(user_wallet: WalletFile, client_shell: Shell):
|
|||
def locked_storage_object(
|
||||
user_container: StorageContainer,
|
||||
client_shell: Shell,
|
||||
cluster: Cluster,
|
||||
request: FixtureRequest,
|
||||
):
|
||||
with allure.step(f"Creating locked object"):
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
with allure.step("Creating locked object"):
|
||||
current_epoch = ensure_fresh_epoch(client_shell, cluster)
|
||||
expiration_epoch = current_epoch + FIXTURE_LOCK_LIFETIME
|
||||
|
||||
storage_object = user_container.generate_object(
|
||||
|
@ -89,6 +77,7 @@ def locked_storage_object(
|
|||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
cluster.default_rpc_endpoint,
|
||||
lifetime=FIXTURE_LOCK_LIFETIME,
|
||||
)
|
||||
storage_object.locks = [
|
||||
|
@ -99,20 +88,21 @@ def locked_storage_object(
|
|||
|
||||
yield storage_object
|
||||
|
||||
with allure.step(f"Delete created locked object"):
|
||||
current_epoch = get_epoch(client_shell)
|
||||
with allure.step("Delete created locked object"):
|
||||
current_epoch = get_epoch(client_shell, cluster)
|
||||
epoch_diff = expiration_epoch - current_epoch + 1
|
||||
|
||||
if epoch_diff > 0:
|
||||
with allure.step(f"Tick {epoch_diff} epochs"):
|
||||
for _ in range(epoch_diff):
|
||||
tick_epoch(client_shell)
|
||||
tick_epoch(client_shell, cluster)
|
||||
try:
|
||||
delete_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
cluster.default_rpc_endpoint,
|
||||
)
|
||||
except Exception as ex:
|
||||
ex_message = str(ex)
|
||||
|
@ -126,7 +116,30 @@ def locked_storage_object(
|
|||
|
||||
@pytest.mark.sanity
|
||||
@pytest.mark.grpc_object_lock
|
||||
class TestObjectLockWithGrpc:
|
||||
class TestObjectLockWithGrpc(ClusterTestBase):
|
||||
def get_storage_object_chunks(self, storage_object: StorageObjectInfo):
|
||||
with allure.step(f"Get complex object chunks (f{storage_object.oid})"):
|
||||
split_object_id = get_link_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
self.shell,
|
||||
self.cluster.storage_nodes,
|
||||
is_direct=False,
|
||||
)
|
||||
head = head_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
split_object_id,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
chunks_object_ids = []
|
||||
if "split" in head["header"] and "children" in head["header"]["split"]:
|
||||
chunks_object_ids = head["header"]["split"]["children"]
|
||||
return chunks_object_ids
|
||||
|
||||
@allure.title("Locked object should be protected from deletion")
|
||||
@pytest.mark.parametrize(
|
||||
"locked_storage_object",
|
||||
|
@ -136,7 +149,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_locked_object_cannot_be_deleted(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
):
|
||||
|
@ -152,7 +164,8 @@ class TestObjectLockWithGrpc:
|
|||
locked_storage_object.wallet_file_path,
|
||||
locked_storage_object.cid,
|
||||
locked_storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@allure.title("Lock object itself should be protected from deletion")
|
||||
|
@ -160,7 +173,6 @@ class TestObjectLockWithGrpc:
|
|||
@pytest.mark.parametrize("locked_storage_object", [SIMPLE_OBJ_SIZE], indirect=True)
|
||||
def test_lock_object_itself_cannot_be_deleted(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
):
|
||||
"""
|
||||
|
@ -171,14 +183,19 @@ class TestObjectLockWithGrpc:
|
|||
wallet_path = locked_storage_object.wallet_file_path
|
||||
|
||||
with pytest.raises(Exception, match=LOCK_OBJECT_REMOVAL):
|
||||
delete_object(wallet_path, lock_object.cid, lock_object.oid, client_shell)
|
||||
delete_object(
|
||||
wallet_path,
|
||||
lock_object.cid,
|
||||
lock_object.oid,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@allure.title("Lock object itself cannot be locked")
|
||||
# We operate with only lock object here so no complex object needed in this test
|
||||
@pytest.mark.parametrize("locked_storage_object", [SIMPLE_OBJ_SIZE], indirect=True)
|
||||
def test_lock_object_cannot_be_locked(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
):
|
||||
"""
|
||||
|
@ -189,7 +206,14 @@ class TestObjectLockWithGrpc:
|
|||
wallet_path = locked_storage_object.wallet_file_path
|
||||
|
||||
with pytest.raises(Exception, match=LOCK_NON_REGULAR_OBJECT):
|
||||
lock_object(wallet_path, lock_object_info.cid, lock_object_info.oid, client_shell, 1)
|
||||
lock_object(
|
||||
wallet_path,
|
||||
lock_object_info.cid,
|
||||
lock_object_info.oid,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
1,
|
||||
)
|
||||
|
||||
@allure.title("Cannot lock object without lifetime and expire_at fields")
|
||||
# We operate with only lock object here so no complex object needed in this test
|
||||
|
@ -207,7 +231,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_cannot_lock_object_without_lifetime(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
wrong_lifetime: int,
|
||||
wrong_expire_at: int,
|
||||
|
@ -228,7 +251,8 @@ class TestObjectLockWithGrpc:
|
|||
wallet_path,
|
||||
lock_object_info.cid,
|
||||
lock_object_info.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
lifetime=wrong_lifetime,
|
||||
expire_at=wrong_expire_at,
|
||||
)
|
||||
|
@ -239,7 +263,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_expired_object_should_be_deleted_after_locks_are_expired(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
user_container: StorageContainer,
|
||||
object_size: int,
|
||||
|
@ -251,7 +274,7 @@ class TestObjectLockWithGrpc:
|
|||
f"Expired object should be deleted after locks are expired for {request.node.callspec.id}"
|
||||
)
|
||||
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
current_epoch = self.ensure_fresh_epoch()
|
||||
storage_object = user_container.generate_object(object_size, expire_at=current_epoch + 1)
|
||||
|
||||
with allure.step("Lock object for couple epochs"):
|
||||
|
@ -259,20 +282,22 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
lifetime=3,
|
||||
)
|
||||
lock_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
expire_at=current_epoch + 3,
|
||||
)
|
||||
|
||||
with allure.step("Check object is not deleted at expiration time"):
|
||||
tick_epoch(client_shell)
|
||||
tick_epoch(client_shell)
|
||||
self.tick_epoch()
|
||||
self.tick_epoch()
|
||||
# Must wait to ensure object is not deleted
|
||||
wait_for_gc_pass_on_storage_nodes()
|
||||
with expect_not_raises():
|
||||
|
@ -280,7 +305,8 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@wait_for_success(parse_time(STORAGE_GC_TIME))
|
||||
|
@ -290,11 +316,12 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
with allure.step("Wait for object to be deleted after third epoch"):
|
||||
tick_epoch(client_shell)
|
||||
self.tick_epoch()
|
||||
check_object_not_found()
|
||||
|
||||
@allure.title("Should be possible to lock multiple objects at once")
|
||||
|
@ -305,7 +332,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_should_be_possible_to_lock_multiple_objects_at_once(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
user_container: StorageContainer,
|
||||
object_size: int,
|
||||
|
@ -317,7 +343,7 @@ class TestObjectLockWithGrpc:
|
|||
f"Should be possible to lock multiple objects at once for {request.node.callspec.id}"
|
||||
)
|
||||
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
current_epoch = ensure_fresh_epoch(self.shell, self.cluster)
|
||||
storage_objects: list[StorageObjectInfo] = []
|
||||
|
||||
with allure.step("Generate three objects"):
|
||||
|
@ -330,7 +356,8 @@ class TestObjectLockWithGrpc:
|
|||
storage_objects[0].wallet_file_path,
|
||||
storage_objects[0].cid,
|
||||
",".join([storage_object.oid for storage_object in storage_objects]),
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
expire_at=current_epoch + 1,
|
||||
)
|
||||
|
||||
|
@ -341,15 +368,16 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
with allure.step("Tick two epochs"):
|
||||
tick_epoch(client_shell)
|
||||
tick_epoch(client_shell)
|
||||
self.tick_epoch()
|
||||
self.tick_epoch()
|
||||
|
||||
with expect_not_raises():
|
||||
delete_objects(storage_objects, client_shell)
|
||||
delete_objects(storage_objects, self.shell, self.cluster)
|
||||
|
||||
@allure.title("Already outdated lock should not be applied")
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -359,7 +387,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_already_outdated_lock_should_not_be_applied(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
user_container: StorageContainer,
|
||||
object_size: int,
|
||||
|
@ -371,7 +398,7 @@ class TestObjectLockWithGrpc:
|
|||
f"Already outdated lock should not be applied for {request.node.callspec.id}"
|
||||
)
|
||||
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
current_epoch = self.ensure_fresh_epoch()
|
||||
|
||||
storage_object = user_container.generate_object(object_size, expire_at=current_epoch + 1)
|
||||
|
||||
|
@ -386,7 +413,8 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
expire_at=expiration_epoch,
|
||||
)
|
||||
|
||||
|
@ -399,7 +427,6 @@ class TestObjectLockWithGrpc:
|
|||
@expect_not_raises()
|
||||
def test_after_lock_expiration_with_lifetime_user_should_be_able_to_delete_object(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
user_container: StorageContainer,
|
||||
object_size: int,
|
||||
|
@ -411,22 +438,27 @@ class TestObjectLockWithGrpc:
|
|||
f"After lock expiration with lifetime user should be able to delete object for {request.node.callspec.id}"
|
||||
)
|
||||
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
current_epoch = self.ensure_fresh_epoch()
|
||||
storage_object = user_container.generate_object(object_size, expire_at=current_epoch + 1)
|
||||
|
||||
lock_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
lifetime=1,
|
||||
)
|
||||
|
||||
tick_epoch(client_shell)
|
||||
|
||||
delete_object(
|
||||
storage_object.wallet_file_path, storage_object.cid, storage_object.oid, client_shell
|
||||
)
|
||||
self.tick_epoch()
|
||||
with expect_not_raises():
|
||||
delete_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@allure.title("After lock expiration with expire_at user should be able to delete object")
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -437,7 +469,6 @@ class TestObjectLockWithGrpc:
|
|||
@expect_not_raises()
|
||||
def test_after_lock_expiration_with_expire_at_user_should_be_able_to_delete_object(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
request: FixtureRequest,
|
||||
user_container: StorageContainer,
|
||||
object_size: int,
|
||||
|
@ -449,7 +480,7 @@ class TestObjectLockWithGrpc:
|
|||
f"After lock expiration with expire_at user should be able to delete object for {request.node.callspec.id}"
|
||||
)
|
||||
|
||||
current_epoch = ensure_fresh_epoch(client_shell)
|
||||
current_epoch = self.ensure_fresh_epoch()
|
||||
|
||||
storage_object = user_container.generate_object(object_size, expire_at=current_epoch + 5)
|
||||
|
||||
|
@ -457,15 +488,21 @@ class TestObjectLockWithGrpc:
|
|||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
endpoint=self.cluster.default_rpc_endpoint,
|
||||
expire_at=current_epoch + 1,
|
||||
)
|
||||
|
||||
tick_epoch(client_shell)
|
||||
self.tick_epoch()
|
||||
|
||||
delete_object(
|
||||
storage_object.wallet_file_path, storage_object.cid, storage_object.oid, client_shell
|
||||
)
|
||||
with expect_not_raises():
|
||||
delete_object(
|
||||
storage_object.wallet_file_path,
|
||||
storage_object.cid,
|
||||
storage_object.oid,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@allure.title("Complex object chunks should also be protected from deletion")
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -476,14 +513,13 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_complex_object_chunks_should_also_be_protected_from_deletion(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
):
|
||||
"""
|
||||
Complex object chunks should also be protected from deletion
|
||||
"""
|
||||
|
||||
chunk_object_ids = get_storage_object_chunks(locked_storage_object, client_shell)
|
||||
chunk_object_ids = self.get_storage_object_chunks(locked_storage_object)
|
||||
for chunk_object_id in chunk_object_ids:
|
||||
with allure.step(f"Try to delete chunk object {chunk_object_id}"):
|
||||
with pytest.raises(Exception, match=OBJECT_IS_LOCKED):
|
||||
|
@ -491,7 +527,8 @@ class TestObjectLockWithGrpc:
|
|||
locked_storage_object.wallet_file_path,
|
||||
locked_storage_object.cid,
|
||||
chunk_object_id,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
||||
@allure.title("Link object of complex object should also be protected from deletion")
|
||||
|
@ -503,7 +540,6 @@ class TestObjectLockWithGrpc:
|
|||
)
|
||||
def test_link_object_of_complex_object_should_also_be_protected_from_deletion(
|
||||
self,
|
||||
client_shell: Shell,
|
||||
locked_storage_object: StorageObjectInfo,
|
||||
):
|
||||
"""
|
||||
|
@ -514,7 +550,8 @@ class TestObjectLockWithGrpc:
|
|||
locked_storage_object.wallet_file_path,
|
||||
locked_storage_object.cid,
|
||||
locked_storage_object.oid,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.storage_nodes,
|
||||
is_direct=False,
|
||||
)
|
||||
with allure.step(f"Try to delete link object {link_object_id}"):
|
||||
|
@ -523,5 +560,6 @@ class TestObjectLockWithGrpc:
|
|||
locked_storage_object.wallet_file_path,
|
||||
locked_storage_object.cid,
|
||||
link_object_id,
|
||||
client_shell,
|
||||
self.shell,
|
||||
self.cluster.default_rpc_endpoint,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue