882 lines
45 KiB
Python
882 lines
45 KiB
Python
import allure
|
|
import pytest
|
|
from frostfs_testlib import reporter
|
|
from frostfs_testlib.steps.cli.container import create_container, delete_container
|
|
from frostfs_testlib.steps.cli.object import delete_object, put_object_to_random_node
|
|
from frostfs_testlib.steps.node_management import get_netmap_snapshot
|
|
from frostfs_testlib.steps.storage_policy import get_nodes_with_object
|
|
from frostfs_testlib.storage.dataclasses.object_size import ObjectSize
|
|
from frostfs_testlib.storage.dataclasses.wallet import WalletInfo
|
|
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
|
|
from frostfs_testlib.utils.cli_utils import parse_netmap_output
|
|
from frostfs_testlib.utils.file_utils import generate_file
|
|
|
|
from ...helpers.container_request import PUBLIC_WITH_POLICY, ContainerRequest
|
|
from ...helpers.policy_validation import get_netmap_param, validate_object_policy
|
|
from ...resources.policy_error_patterns import NOT_ENOUGH_TO_SELECT, NOT_FOUND_FILTER, NOT_FOUND_SELECTOR, NOT_PARSE_POLICY
|
|
|
|
|
|
@pytest.mark.nightly
|
|
@pytest.mark.policy
|
|
class TestPolicy(ClusterTestBase):
|
|
@allure.title("[NEGATIVE] Placement policy: Can't parse placement policy")
|
|
def test_placement_policy_negative(self, default_wallet: WalletInfo, rpc_endpoint: str):
|
|
"""
|
|
Negative test for placement policy: Can't parse placement policy.
|
|
"""
|
|
placement_rule = "REP 1 IN SPB REP 1 in MSK CBF 1 SELECT 1 FROM SPBRU AS SPB SELECT 1 FROM MSKRU AS MSK FILTER SubDivCode EQ SPE AS SPBRU FILTER NOT (Country EQ Sweden OR CountryCode EQ FI) AND Location EQ Moskva AS MSKRU"
|
|
|
|
with reporter.step(f"Create container with policy {placement_rule}"):
|
|
with pytest.raises(Exception, match=NOT_PARSE_POLICY):
|
|
create_container(default_wallet, self.shell, rpc_endpoint, placement_rule)
|
|
|
|
@allure.title("[NEGATIVE] Placement policy: Not enough nodes to SELECT")
|
|
def test_placement_policy_negative_not_enough_nodes_to_select(self, default_wallet: WalletInfo, rpc_endpoint: str):
|
|
"""
|
|
Negative test for placement policy: Not enough nodes to SELECT.
|
|
"""
|
|
placement_rule = "REP 2 IN RU SELECT 2 FROM RUS AS RU FILTER Country EQ Russia AND SubDivCode EQ SPE AS RUS"
|
|
|
|
with reporter.step(f"Create container with policy {placement_rule}"):
|
|
with pytest.raises(Exception, match=NOT_ENOUGH_TO_SELECT):
|
|
create_container(default_wallet, self.shell, rpc_endpoint, placement_rule)
|
|
|
|
@allure.title("[NEGATIVE] Placement policy: Filter not found")
|
|
def test_placement_policy_negative_not_enough_nodes_to_filter(self, default_wallet: WalletInfo, rpc_endpoint: str):
|
|
"""
|
|
Negative test for placement policy: Filter not found.
|
|
"""
|
|
placement_rule = (
|
|
"REP 2 IN HALF CBF 1 SELECT 2 FROM GT15 AS HALF FILTER @NOTRU AND Price GT 15 AS GT15 FILTER CountryCode NE RU AS NOTRU"
|
|
)
|
|
|
|
with reporter.step(f"Create container with policy {placement_rule}"):
|
|
with pytest.raises(Exception, match=NOT_FOUND_FILTER):
|
|
create_container(default_wallet, self.shell, rpc_endpoint, placement_rule)
|
|
|
|
@allure.title("[NEGATIVE] Placement policy: SELECTOR not found")
|
|
def test_placement_policy_negative_not_enough_nodes_to_selector(self, default_wallet: WalletInfo, rpc_endpoint: str):
|
|
"""
|
|
Negative test for placement policy: Filter not found.
|
|
"""
|
|
placement_rule = "REP 2 IN HALFIC CBF 1 SELECT 2 FROM GT15 AS HALF FILTER Price GT 15 AS GT15"
|
|
|
|
with reporter.step(f"Create container with policy {placement_rule}"):
|
|
with pytest.raises(Exception, match=NOT_FOUND_SELECTOR):
|
|
create_container(default_wallet, self.shell, rpc_endpoint, placement_rule)
|
|
|
|
@allure.title("Simple policy results with one node")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 1 REP 1 CBF 1")], indirect=True)
|
|
def test_simple_policy_results_with_one_node(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement simple policy results with one node.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with one node")
|
|
@pytest.mark.parametrize(
|
|
"container_request", [PUBLIC_WITH_POLICY("REP 1 IN AnyNode REP 1 IN AnyNode CBF 1 SELECT 1 FROM * AS AnyNode")], indirect=True
|
|
)
|
|
def test_policy_with_select_results_with_one_node(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with one node.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT and FILTER results with one node")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"REP 1 IN MyRussianNodes REP 1 IN MyRussianNodes CBF 1 SELECT 1 FROM RussianNodes AS MyRussianNodes FILTER Country EQ 'Russia' AS RussianNodes"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_and_filter_results_with_one_node(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT and FILTER results with one node.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
placement_params = {"country": "Russia"}
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
node_address = resulting_copies[0].get_rpc_endpoint().split(":")[0]
|
|
with reporter.step(f"Check the node is selected from {placement_params['country']}"):
|
|
assert (
|
|
placement_params["country"] == netmap[node_address]["country"]
|
|
), f"The node is selected from the wrong country. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT and Complex FILTER results with one node")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"REP 1 IN RUS REP 1 IN RUS CBF 1 SELECT 1 FROM RU AS RUS FILTER Country NE Sweden AS NotSE FILTER @NotSE AND NOT (CountryCode EQ FI) AND Country EQ 'Russia' AS RU"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_and_complex_filter_results_with_one_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT and Complex FILTER results with one node.
|
|
"""
|
|
placement_params = {"country": ["Russia", "Sweden"], "country_code": "FI"}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
node_address = resulting_copies[0].get_rpc_endpoint().split(":")[0]
|
|
with reporter.step(f"Check the node is selected from {placement_params['country'][0]}"):
|
|
assert (
|
|
not (placement_params["country"][1] == netmap[node_address]["country"])
|
|
or not (placement_params["country"][1] == netmap[node_address]["country"])
|
|
and not (placement_params["country_code"] == netmap[node_address]["country_code"])
|
|
and (placement_params["country"][0] == netmap[node_address]["country"])
|
|
), f"The node is selected from the wrong country or country code. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with Multi SELECTs and FILTERs results with one node")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"REP 1 IN RU REP 1 IN EU REP 1 IN RU CBF 1 SELECT 1 FROM RUS AS RU SELECT 1 FROM EUR AS EU FILTER Country EQ Russia AS RUS FILTER NOT (@RUS) AND Country EQ Sweden OR CountryCode EQ FI AS EUR"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_multi_selects_and_filters_results_with_one_node(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with Multi SELECTs and FILTERs results with one nodes.
|
|
"""
|
|
placement_params = {"country": ["Sweden", "Russia"], "country_code": "FI"}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
with reporter.step(f"Check two nodes are selected from any country"):
|
|
for node in resulting_copies:
|
|
node_address = resulting_copies[0].get_rpc_endpoint().split(":")[0]
|
|
assert (placement_params["country"][1] == netmap[node_address]["country"]) or (
|
|
not (placement_params["country"][1] == netmap[node_address]["country"])
|
|
and (placement_params["country"][0] == netmap[node_address]["country"])
|
|
or (placement_params["country_code"] == netmap[node_address]["country_code"])
|
|
), f"The node is selected from the wrong country or country code. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT and FILTER results with UNIQUE nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"UNIQUE REP 1 IN MyRussianNodes REP 1 IN MyRussianNodes CBF 1 SELECT 1 FROM RussianNodes AS MyRussianNodes FILTER Country EQ 'Russia' AS RussianNodes"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_and_filter_results_with_unique_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT and FILTER results with UNIQUE nodes.
|
|
"""
|
|
placement_params = {"country": "Russia"}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
with reporter.step(f"Check two nodes are selected from {placement_params['country']}"):
|
|
for node in resulting_copies:
|
|
node_address = node.get_rpc_endpoint().split(":")[0]
|
|
assert (
|
|
placement_params["country"] == netmap[node_address]["country"]
|
|
), f"The node is selected from the wrong country. Got {netmap[node_address]['country']}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Simple policy results with 25% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 1 CBF 1")], indirect=True)
|
|
def test_simple_policy_results_with_25_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy results with 25% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with 25% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 1 IN One CBF 1 SELECT 1 FROM * AS One")], indirect=True)
|
|
def test_policy_with_select_results_with_25_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with 25% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Simple policy results with 50% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 2 CBF 1")], indirect=True)
|
|
def test_simple_policy_results_with_50_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement simple policy results with 50% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with 50% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 2 IN HALF CBF 1 SELECT 2 FROM * AS HALF")], indirect=True)
|
|
def test_policy_with_select_results_with_50_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with 50% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Simple policy results with 75% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 1")], indirect=True)
|
|
def test_simple_policy_results_with_75_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement simple policy results with 75% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with 75% of available nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request", [PUBLIC_WITH_POLICY("REP 2 IN DS CBF 1 SELECT 3 IN DISTINCT Country FROM * AS DS")], indirect=True
|
|
)
|
|
def test_policy_with_select_results_with_75_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with 75% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Simple policy results with 100% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 4")], indirect=True)
|
|
def test_simple_policy_results_with_100_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement simple policy results with 100% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 4
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with 100% of available nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("REP 1 IN All SELECT 4 FROM * AS All")], indirect=True)
|
|
def test_policy_with_select_results_with_100_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with 100% of available nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 1
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT and Complex FILTER results with 100% of available nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"REP 2 IN All SELECT 4 FROM AllNodes AS All FILTER Country EQ Russia OR Country EQ Sweden OR Country EQ Finland AS AllCountries FILTER @AllCountries AND Continent EQ Europe AS AllNodes"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_and_complex_filter_results_with_100_of_available_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT and Complex FILTER results with 100% of available nodes.
|
|
"""
|
|
placement_params = {"country": ["Russia", "Sweden", "Finland"], "continent": "Europe"}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
with reporter.step(f"Check two nodes are selected from {' or '.join(placement_params['country'])}"):
|
|
for node in resulting_copies:
|
|
node_address = node.get_rpc_endpoint().split(":")[0]
|
|
assert (
|
|
(netmap[node_address]["country"] in placement_params["country"])
|
|
or (netmap[node_address]["country"] in placement_params["country"])
|
|
and (netmap[node_address]["continent"] == placement_params["continent"])
|
|
), f"The node is selected from the wrong country or continent. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Simple policy results with UNIQUE nodes")
|
|
@pytest.mark.parametrize("container_request", [PUBLIC_WITH_POLICY("UNIQUE REP 1 REP 1 CBF 1")], indirect=True)
|
|
def test_simple_policy_results_with_unique_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement simple policy results with UNIQUE nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT results with UNIQUE nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[PUBLIC_WITH_POLICY("UNIQUE REP 1 IN AnyNode REP 1 IN AnyNode CBF 1 SELECT 1 FROM * AS AnyNode")],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_results_with_unique_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT results with UNIQUE nodes.
|
|
"""
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with SELECT and Complex FILTER results with UNIQUE nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"UNIQUE REP 1 IN RUS REP 1 IN RUS CBF 1 SELECT 1 FROM RU AS RUS FILTER Country NE Sweden AS NotSE FILTER @NotSE AND NOT (CountryCode EQ FI) AND Country EQ 'Russia' AS RU"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_select_and_complex_filter_results_with_unique_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with SELECT and Complex FILTER results with UNIQUE nodes.
|
|
"""
|
|
placement_params = {"country_code": "FI", "country": ["Sweden", "Russia"]}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 2
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
with reporter.step(f"Check two nodes are selected not from {placement_params['country'][0]}"):
|
|
for node in resulting_copies:
|
|
node_address = node.get_rpc_endpoint().split(":")[0]
|
|
assert not (placement_params["country"][0] == netmap[node_address]["country"]) or (
|
|
not (placement_params["country"][0] == netmap[node_address]["country"])
|
|
and not (placement_params["country_code"] == netmap[node_address]["country_code"])
|
|
and placement_params["country"][1] == netmap[node_address]["country"]
|
|
), f"The node is selected from the wrong country or with wrong country code. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy with Multi SELECTs and FILTERs results with UNIQUE nodes")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"UNIQUE REP 1 IN RU REP 1 IN EU REP 1 IN RU CBF 1 SELECT 1 FROM RUS AS RU SELECT 1 FROM EUR AS EU FILTER Country EQ Russia AS RUS FILTER NOT (@RUS) AND Country EQ Sweden OR CountryCode EQ FI AS EUR"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_with_multi_selects_and_filters_results_with_unique_nodes(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy with Multi SELECTs and FILTERs results with UNIQUE nodes.
|
|
"""
|
|
placement_params = {"country": ["Russia", "Sweden"], "country_code": "FI"}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 3
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) == expected_copies, f"Expected {expected_copies} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
with reporter.step(f"Check three nodes are selected from any country"):
|
|
for node in resulting_copies:
|
|
node_address = node.get_rpc_endpoint().split(":")[0]
|
|
assert (placement_params["country"][0] == netmap[node_address]["country"]) or (
|
|
not (placement_params["country"][0] == netmap[node_address]["country"])
|
|
and (placement_params["country"][1] == netmap[node_address]["country"])
|
|
or (placement_params["country_code"] == netmap[node_address]["country_code"])
|
|
), f"The node is selected from the wrong country or with wrong country code. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|
|
|
|
@allure.title("Policy: REP 1 IN SPB REP 1 IN MSK REP 3")
|
|
@pytest.mark.parametrize(
|
|
"container_request",
|
|
[
|
|
PUBLIC_WITH_POLICY(
|
|
"REP 1 IN SPB REP 1 IN MSK REP 3 CBF 1 SELECT 2 FROM LED AS SPB SELECT 2 FROM MOW AS MSK FILTER Location EQ 'Saint Petersburg (ex Leningrad)' AS LED FILTER Location EQ Moskva AS MOW"
|
|
)
|
|
],
|
|
indirect=True,
|
|
)
|
|
def test_policy_rep_1_in_spb_rep_1_in_msk_rep_3(
|
|
self,
|
|
default_wallet: WalletInfo,
|
|
rpc_endpoint: str,
|
|
simple_object_size: ObjectSize,
|
|
container: str,
|
|
container_request: ContainerRequest,
|
|
):
|
|
"""
|
|
This test checks object's copies based on container's placement policy: REP 1 IN SPB REP 1 IN MSK REP 3.
|
|
"""
|
|
placement_params = {"location": ["Saint Petersburg (ex Leningrad)", "Moskva"]}
|
|
file_path = generate_file(simple_object_size.value)
|
|
expected_copies = 3
|
|
|
|
with reporter.step(f"Check container policy"):
|
|
validate_object_policy(default_wallet, self.shell, container_request.policy, container, rpc_endpoint)
|
|
|
|
with reporter.step(f"Put object in container"):
|
|
oid = put_object_to_random_node(default_wallet, file_path, container, self.shell, self.cluster)
|
|
|
|
with reporter.step(f"Check object expected copies"):
|
|
resulting_copies = get_nodes_with_object(container, oid, self.shell, self.cluster.storage_nodes)
|
|
assert len(resulting_copies) >= expected_copies and len(resulting_copies) <= len(
|
|
self.cluster.storage_nodes
|
|
), f"Expected {expected_copies} or {expected_copies + 1} copies, got {len(resulting_copies)}"
|
|
|
|
with reporter.step(f"Check the object appearance"):
|
|
netmap = parse_netmap_output(get_netmap_snapshot(node=resulting_copies[0], shell=self.shell))
|
|
netmap = get_netmap_param(netmap)
|
|
list_of_location = []
|
|
for node in resulting_copies:
|
|
node_address = node.get_rpc_endpoint().split(":")[0]
|
|
list_of_location.append(netmap[node_address]["location"])
|
|
|
|
with reporter.step(f"Check two or three nodes are selected from Russia and from any other country"):
|
|
assert (
|
|
placement_params["location"][0] in list_of_location
|
|
and placement_params["location"][1] in list_of_location
|
|
and len(resulting_copies) > 2
|
|
), f"The node is selected from the wrong location. Got {netmap[node_address]}"
|
|
|
|
with reporter.step(f"Delete the object from the container"):
|
|
delete_object(default_wallet, container, oid, self.shell, rpc_endpoint)
|
|
|
|
with reporter.step(f"Delete the container"):
|
|
delete_container(default_wallet, container, self.shell, rpc_endpoint, await_mode=False)
|