[#205] storage policy validation reconsidered
Signed-off-by: anastasia prasolova <anastasia@nspcc.ru>
This commit is contained in:
parent
8116ada7b6
commit
e4c1c23ddd
9 changed files with 203 additions and 156 deletions
|
@ -32,7 +32,7 @@ def get_scripthash(wif: str):
|
|||
|
||||
|
||||
@keyword('Stop nodes')
|
||||
def stop_nodes(down_num: int, *nodes_list):
|
||||
def stop_nodes(down_num: int, nodes_list: list):
|
||||
|
||||
# select nodes to stop from list
|
||||
nodes = random.sample(nodes_list, down_num)
|
||||
|
@ -44,11 +44,11 @@ def stop_nodes(down_num: int, *nodes_list):
|
|||
client = docker.APIClient()
|
||||
client.stop(node)
|
||||
|
||||
return stop_nodes
|
||||
return nodes
|
||||
|
||||
|
||||
@keyword('Start nodes')
|
||||
def start_nodes(*nodes_list):
|
||||
def start_nodes(nodes_list: list):
|
||||
|
||||
for node in nodes_list:
|
||||
m = re.search(r'(s\d+).', node)
|
||||
|
@ -89,38 +89,6 @@ def get_nodes_without_object(wallet: str, cid: str, oid: str):
|
|||
return nodes_list
|
||||
|
||||
|
||||
@keyword('Validate storage policy for object')
|
||||
def validate_storage_policy_for_object(wallet: str, expected_copies: int, cid, oid,
|
||||
expected_node_list=[], storage_nodes=[]):
|
||||
storage_nodes = storage_nodes if len(storage_nodes) != 0 else NEOFS_NETMAP
|
||||
copies = 0
|
||||
found_nodes = []
|
||||
oid = oid.strip()
|
||||
|
||||
for node in storage_nodes:
|
||||
res = _search_object(node, wallet, cid, oid)
|
||||
if res:
|
||||
if oid in res:
|
||||
copies += 1
|
||||
found_nodes.append(node)
|
||||
|
||||
if copies != expected_copies:
|
||||
raise Exception("Object copies is not match storage policy."
|
||||
f"Found: {copies}, expected: {expected_copies}.")
|
||||
else:
|
||||
logger.info(f"Found copies: {copies}, expected: {expected_copies}")
|
||||
|
||||
logger.info(f"Found nodes: {found_nodes}")
|
||||
|
||||
if expected_node_list:
|
||||
if sorted(found_nodes) == sorted(expected_node_list):
|
||||
logger.info(f"Found node list '{found_nodes}' "
|
||||
f"is equal for expected list '{expected_node_list}'")
|
||||
else:
|
||||
raise Exception(f"Found node list '{found_nodes}' "
|
||||
f"is not equal to expected list '{expected_node_list}'")
|
||||
|
||||
|
||||
@keyword('Verify Head Tombstone')
|
||||
def verify_head_tombstone(wallet: str, cid: str, oid_ts: str, oid: str, addr: str):
|
||||
# TODO: replace with HEAD from neofs_verbs.py
|
||||
|
@ -212,7 +180,7 @@ def get_logs_latest_timestamp():
|
|||
log_line = client_api.logs(container, tail=1)
|
||||
|
||||
m = re.search(r'(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z)', str(log_line))
|
||||
if m != None:
|
||||
if m is not None:
|
||||
timestamp = m.group(1)
|
||||
|
||||
timestamp_date = datetime.fromisoformat(timestamp[:-1])
|
||||
|
@ -307,29 +275,6 @@ def sign_session_token(session_token: str, wallet: str, to_file: str=''):
|
|||
_cmd_run(cmd)
|
||||
|
||||
|
||||
def _parse_oid(input_str: str):
|
||||
"""
|
||||
This function parses OID from given CLI output. The input string we
|
||||
expect:
|
||||
Object successfully stored
|
||||
ID: 4MhrLA7RXTBXCsaNnbahYVAPuoQdiUPuyNEWnywvoSEs
|
||||
CID: HeZu2DXBuPve6HXbuHZx64knS7KcGtfSj2L59Li72kkg
|
||||
We want to take 'ID' value from the string.
|
||||
|
||||
Parameters:
|
||||
- input_str: a string with command run output
|
||||
"""
|
||||
try:
|
||||
# taking second string from command output
|
||||
snd_str = input_str.split('\n')[1]
|
||||
except:
|
||||
logger.error(f"Got empty input: {input_str}")
|
||||
splitted = snd_str.split(": ")
|
||||
if len(splitted) != 2:
|
||||
raise Exception(f"no OID was parsed from command output: \t{snd_str}")
|
||||
return splitted[1]
|
||||
|
||||
|
||||
def _search_object(node:str, wallet: str, cid:str, oid: str):
|
||||
cmd = (
|
||||
f'{NEOFS_CLI_EXEC} --rpc-endpoint {node} --wallet {wallet} --ttl 1 '
|
||||
|
|
|
@ -247,7 +247,12 @@ def head_object(wallet: str, cid: str, oid: str, bearer_token: str="",
|
|||
f'{"--raw" if is_raw else ""} '
|
||||
f'{"--ttl 1" if is_direct else ""}'
|
||||
)
|
||||
output = None
|
||||
try:
|
||||
output = _cmd_run(cmd)
|
||||
except Exception as exc:
|
||||
logger.info(f"Head request failed with output: {output}")
|
||||
return None
|
||||
|
||||
if not json_output:
|
||||
return output
|
||||
|
|
79
robot/resources/lib/python/storage_policy.py
Normal file
79
robot/resources/lib/python/storage_policy.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
'''
|
||||
This module contains keywords which are used for asserting
|
||||
that storage policies are kept.
|
||||
'''
|
||||
|
||||
from common import NEOFS_NETMAP
|
||||
import complex_object_actions
|
||||
import neofs_verbs
|
||||
|
||||
from robot.api.deco import keyword
|
||||
|
||||
ROBOT_AUTO_KEYWORDS = False
|
||||
|
||||
|
||||
@keyword('Get Object Copies')
|
||||
def get_object_copies(complexity: str, wallet: str, cid: str, oid: str):
|
||||
"""
|
||||
The function performs requests to all nodes of the container and
|
||||
finds out if they store a copy of the object. The procedure is
|
||||
different for simple and complex object, so the function requires
|
||||
a sign of object complexity.
|
||||
Args:
|
||||
complexity (str): the tag of object size and complexity,
|
||||
[Simple|Complex]
|
||||
wallet (str): the path to the wallet on whose behalf the
|
||||
copies are got
|
||||
cid (str): ID of the container
|
||||
oid (str): ID of the Object
|
||||
Returns:
|
||||
(int): the number of object copies in the container
|
||||
"""
|
||||
return (get_simple_object_copies(wallet, cid, oid) if complexity == "Simple"
|
||||
else get_complex_object_copies(wallet, cid, oid))
|
||||
|
||||
|
||||
@keyword('Get Simple Object Copies')
|
||||
def get_simple_object_copies(wallet: str, cid: str, oid: str):
|
||||
"""
|
||||
To figure out the number of a simple object copies, only direct
|
||||
HEAD requests should be made to the every node of the container.
|
||||
We consider non-empty HEAD response as a stored object copy.
|
||||
Args:
|
||||
wallet (str): the path to the wallet on whose behalf the
|
||||
copies are got
|
||||
cid (str): ID of the container
|
||||
oid (str): ID of the Object
|
||||
Returns:
|
||||
(int): the number of object copies in the container
|
||||
"""
|
||||
copies = 0
|
||||
for node in NEOFS_NETMAP:
|
||||
response = neofs_verbs.head_object(wallet, cid, oid,
|
||||
endpoint=node,
|
||||
is_direct=True)
|
||||
if response:
|
||||
copies += 1
|
||||
return copies
|
||||
|
||||
|
||||
@keyword('Get Complex Object Copies')
|
||||
def get_complex_object_copies(wallet: str, cid: str, oid: str):
|
||||
"""
|
||||
To figure out the number of a complex object copies, we firstly
|
||||
need to retrieve its Last object. We consider that the number of
|
||||
complex object copies is equal to the number of its last object
|
||||
copies. When we have the Last object ID, the task is reduced
|
||||
to getting simple object copies.
|
||||
Args:
|
||||
wallet (str): the path to the wallet on whose behalf the
|
||||
copies are got
|
||||
cid (str): ID of the container
|
||||
oid (str): ID of the Object
|
||||
Returns:
|
||||
(int): the number of object copies in the container
|
||||
"""
|
||||
last_oid = complex_object_actions.get_last_object(wallet, cid, oid)
|
||||
return get_simple_object_copies(wallet, cid, last_oid)
|
|
@ -49,7 +49,6 @@ def get_file_hash(filename: str):
|
|||
with open(filename, "rb") as out:
|
||||
for block in iter(lambda: out.read(blocksize), b""):
|
||||
file_hash.update(block)
|
||||
logger.info(f"Hash: {file_hash.hexdigest()}")
|
||||
return file_hash.hexdigest()
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
*** Settings ***
|
||||
Variables common.py
|
||||
|
||||
Library acl.py
|
||||
Library container.py
|
||||
Library contract_keywords.py
|
||||
Library neofs.py
|
||||
Library neofs_verbs.py
|
||||
Library acl.py
|
||||
Library contract_keywords.py
|
||||
Library storage_policy.py
|
||||
Library utility_keywords.py
|
||||
|
||||
Resource eacl_tables.robot
|
||||
|
@ -17,8 +18,6 @@ Resource storage.robot
|
|||
*** Variables ***
|
||||
${FULL_PLACEMENT_RULE} = REP 4 IN X CBF 1 SELECT 4 FROM * AS X
|
||||
${EXPECTED_COPIES} = ${4}
|
||||
${DEPOSIT} = ${30}
|
||||
|
||||
|
||||
*** Test cases ***
|
||||
eACL Deny Replication Operations
|
||||
|
@ -41,7 +40,8 @@ eACL Deny Replication Operations
|
|||
|
||||
${OID} = Put object ${WALLET} ${FILE} ${CID}
|
||||
|
||||
Validate storage policy for object ${WALLET} ${EXPECTED_COPIES} ${CID} ${OID}
|
||||
${COPIES} = Get Object Copies Simple ${WALLET} ${CID} ${OID}
|
||||
Should Be Equal As Numbers ${EXPECTED_COPIES} ${COPIES}
|
||||
|
||||
Set eACL ${WALLET} ${CID} ${EACL_DENY_ALL_USER}
|
||||
|
||||
|
@ -52,9 +52,11 @@ eACL Deny Replication Operations
|
|||
Drop object ${NODE} ${WALLET_STORAGE} ${CID} ${OID}
|
||||
|
||||
Tick Epoch
|
||||
Sleep ${NEOFS_CONTRACT_CACHE_TIMEOUT}
|
||||
|
||||
# We assume that during one epoch object should be replicated
|
||||
Wait Until Keyword Succeeds ${NEOFS_EPOCH_TIMEOUT} 1m
|
||||
... Validate storage policy for object ${WALLET_STORAGE} ${EXPECTED_COPIES} ${CID} ${OID}
|
||||
${COPIES} = Get Object Copies Simple ${WALLET_STORAGE} ${CID} ${OID}
|
||||
Should Be Equal As Numbers ${EXPECTED_COPIES} ${COPIES}
|
||||
... msg="Dropped object should be replicated in one epoch"
|
||||
|
||||
[Teardown] Teardown acl_deny_replication
|
||||
|
|
|
@ -4,14 +4,14 @@ Variables common.py
|
|||
Library container.py
|
||||
Library neofs.py
|
||||
Library neofs_verbs.py
|
||||
Library storage_policy.py
|
||||
Library utility_keywords.py
|
||||
|
||||
Library Collections
|
||||
|
||||
Resource payment_operations.robot
|
||||
Resource setup_teardown.robot
|
||||
|
||||
*** Variables ***
|
||||
${CONTAINER_WAIT_INTERVAL} = 1 min
|
||||
|
||||
*** Test cases ***
|
||||
NeoFS Simple Netmap
|
||||
[Documentation] Testcase to validate NeoFS Netmap.
|
||||
|
@ -21,66 +21,77 @@ NeoFS Simple Netmap
|
|||
[Setup] Setup
|
||||
|
||||
${WALLET} ${_} ${_} = Prepare Wallet And Deposit
|
||||
${FILE} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 IN X CBF 2 SELECT 2 FROM * AS X 2 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 2 IN X CBF 2 SELECT 2 FROM * AS X 2
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 IN X CBF 1 SELECT 2 FROM * AS X 2 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 2 IN X CBF 1 SELECT 2 FROM * AS X 2
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 3 IN X CBF 1 SELECT 3 FROM * AS X 3 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 3 IN X CBF 1 SELECT 3 FROM * AS X 3
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 IN X CBF 1 SELECT 1 FROM * AS X 1 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 1 IN X CBF 1 SELECT 1 FROM * AS X 1
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 IN X CBF 2 SELECT 1 FROM * AS X 1 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 1 IN X CBF 2 SELECT 1 FROM * AS X 1
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 4 IN X CBF 1 SELECT 4 FROM * AS X 4 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 4 IN X CBF 1 SELECT 4 FROM * AS X 4
|
||||
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 IN X CBF 1 SELECT 4 FROM * AS X 2 @{EMPTY}
|
||||
Validate Object Copies ${WALLET} REP 2 IN X CBF 1 SELECT 4 FROM * AS X 2
|
||||
|
||||
@{EXPECTED} = Create List s01.neofs.devenv:8080 s02.neofs.devenv:8080 s03.neofs.devenv:8080 s04.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 4 IN X CBF 1 SELECT 4 FROM * AS X 4 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 4 IN X CBF 1 SELECT 4 FROM * AS X 4 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s03.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 IN LOC_PLACE CBF 1 SELECT 1 FROM LOC_SW AS LOC_PLACE FILTER Country EQ Sweden AS LOC_SW
|
||||
Validate Selected Nodes ${WALLET} REP 1 IN LOC_PLACE CBF 1 SELECT 1 FROM LOC_SW AS LOC_PLACE FILTER Country EQ Sweden AS LOC_SW
|
||||
... 1 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s02.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 CBF 1 SELECT 1 FROM LOC_SPB FILTER 'UN-LOCODE' EQ 'RU LED' AS LOC_SPB 1 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 1 CBF 1 SELECT 1 FROM LOC_SPB FILTER 'UN-LOCODE' EQ 'RU LED' AS LOC_SPB 1 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s01.neofs.devenv:8080 s02.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 IN LOC_SPB_PLACE REP 1 IN LOC_MSK_PLACE CBF 1 SELECT 1 FROM LOC_SPB AS LOC_SPB_PLACE SELECT 1 FROM LOC_MSK AS LOC_MSK_PLACE FILTER 'UN-LOCODE' EQ 'RU LED' AS LOC_SPB FILTER 'UN-LOCODE' EQ 'RU MOW' AS LOC_MSK
|
||||
Validate Selected Nodes ${WALLET}
|
||||
... REP 1 IN LOC_SPB_PLACE REP 1 IN LOC_MSK_PLACE CBF 1 SELECT 1 FROM LOC_SPB AS LOC_SPB_PLACE SELECT 1 FROM LOC_MSK AS LOC_MSK_PLACE FILTER 'UN-LOCODE' EQ 'RU LED' AS LOC_SPB FILTER 'UN-LOCODE' EQ 'RU MOW' AS LOC_MSK
|
||||
... 2 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s01.neofs.devenv:8080 s02.neofs.devenv:8080 s03.neofs.devenv:8080 s04.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 4 CBF 1 SELECT 4 FROM LOC_EU FILTER Continent EQ Europe AS LOC_EU 4 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 4 CBF 1 SELECT 4 FROM LOC_EU FILTER Continent EQ Europe AS LOC_EU 4 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s02.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 1 CBF 1 SELECT 1 FROM LOC_SPB FILTER 'UN-LOCODE' NE 'RU MOW' AND 'UN-LOCODE' NE 'SE STO' AND 'UN-LOCODE' NE 'FI HEL' AS LOC_SPB
|
||||
Validate Selected Nodes ${WALLET}
|
||||
... REP 1 CBF 1 SELECT 1 FROM LOC_SPB FILTER 'UN-LOCODE' NE 'RU MOW' AND 'UN-LOCODE' NE 'SE STO' AND 'UN-LOCODE' NE 'FI HEL' AS LOC_SPB
|
||||
... 1 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s01.neofs.devenv:8080 s02.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 CBF 1 SELECT 2 FROM LOC_RU FILTER SubDivCode NE 'AB' AND SubDivCode NE '18' AS LOC_RU 2 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 2 CBF 1 SELECT 2 FROM LOC_RU FILTER SubDivCode NE 'AB' AND SubDivCode NE '18' AS LOC_RU 2 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s01.neofs.devenv:8080 s02.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 CBF 1 SELECT 2 FROM LOC_RU FILTER Country EQ 'Russia' AS LOC_RU 2 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 2 CBF 1 SELECT 2 FROM LOC_RU FILTER Country EQ 'Russia' AS LOC_RU 2 @{EXPECTED}
|
||||
|
||||
@{EXPECTED} = Create List s03.neofs.devenv:8080 s04.neofs.devenv:8080
|
||||
Validate Policy ${WALLET} ${FILE} REP 2 CBF 1 SELECT 2 FROM LOC_EU FILTER Country NE 'Russia' AS LOC_EU 2 @{EXPECTED}
|
||||
Validate Selected Nodes ${WALLET} REP 2 CBF 1 SELECT 2 FROM LOC_EU FILTER Country NE 'Russia' AS LOC_EU 2 @{EXPECTED}
|
||||
|
||||
Log Put operation should be failed with error "not enough nodes to SELECT from: 'X'"
|
||||
Run Keyword And Expect Error *
|
||||
... Validate Policy ${WALLET} ${FILE} REP 2 IN X CBF 2 SELECT 6 FROM * AS X 2 @{EMPTY}
|
||||
${ERR} = Run Keyword And Expect Error *
|
||||
... Validate Selected Nodes ${WALLET} REP 2 IN X CBF 2 SELECT 6 FROM * AS X 2
|
||||
Should Contain ${ERR} code = 1024 message = netmap: not enough nodes to SELECT from
|
||||
|
||||
[Teardown] Teardown netmap_simple
|
||||
|
||||
*** Keywords ***
|
||||
|
||||
Validate Policy
|
||||
[Arguments] ${WALLET} ${FILE} ${POLICY} ${EXPECTED_VAL} @{EXPECTED_LIST}
|
||||
|
||||
Log Container with rule ${POLICY}
|
||||
Validate Object Copies
|
||||
[Arguments] ${WALLET} ${POLICY} ${EXPECTED_COPIES}
|
||||
|
||||
${FILE}
|
||||
... ${_} = Generate file ${SIMPLE_OBJ_SIZE}
|
||||
${CID} = Create container ${WALLET} rule=${POLICY}
|
||||
${S_OID} = Put object ${WALLET} ${FILE} ${CID}
|
||||
Validate storage policy for object ${WALLET} ${EXPECTED_VAL} ${CID} ${S_OID} ${EXPECTED_LIST}
|
||||
Get object ${WALLET} ${CID} ${S_OID} ${EMPTY} s_file_read
|
||||
${OID} = Put object ${WALLET} ${FILE} ${CID}
|
||||
${COPIES} = Get Simple Object Copies ${WALLET} ${CID} ${OID}
|
||||
Should Be Equal As Numbers ${EXPECTED_COPIES} ${COPIES}
|
||||
[Return] ${CID} ${OID}
|
||||
|
||||
|
||||
Validate Selected Nodes
|
||||
[Arguments] ${WALLET} ${POLICY} ${EXPECTED_COPIES} @{EXPECTED_NODES}
|
||||
|
||||
${CID}
|
||||
... ${OID} = Validate Object Copies ${WALLET} ${POLICY} ${EXPECTED_COPIES}
|
||||
${NODES} = Get Nodes With Object ${WALLET} ${CID} ${OID}
|
||||
Lists Should Be Equal ${EXPECTED_NODES} ${NODES}
|
||||
|
|
|
@ -3,9 +3,10 @@ Variables common.py
|
|||
Variables wellknown_acl.py
|
||||
|
||||
Library container.py
|
||||
Library contract_keywords.py
|
||||
Library neofs.py
|
||||
Library neofs_verbs.py
|
||||
Library contract_keywords.py
|
||||
Library storage_policy.py
|
||||
Library utility_keywords.py
|
||||
|
||||
Library Collections
|
||||
|
@ -15,7 +16,6 @@ Resource setup_teardown.robot
|
|||
|
||||
*** Variables ***
|
||||
${EXPECTED_COPIES} = ${2}
|
||||
${CHECK_INTERVAL} = 1 min
|
||||
|
||||
*** Test cases ***
|
||||
NeoFS Object Replication
|
||||
|
@ -26,7 +26,7 @@ NeoFS Object Replication
|
|||
[Setup] Setup
|
||||
|
||||
Log Check replication mechanism
|
||||
Check Replication ${EMPTY}
|
||||
Check Replication
|
||||
Log Check Sticky Bit with SYSTEM Group via replication mechanism
|
||||
Check Replication ${STICKYBIT_PUB_ACL}
|
||||
|
||||
|
@ -34,7 +34,7 @@ NeoFS Object Replication
|
|||
|
||||
*** Keywords ***
|
||||
Check Replication
|
||||
[Arguments] ${ACL}
|
||||
[Arguments] ${ACL}=${EMPTY}
|
||||
|
||||
${WALLET} ${_} ${_} = Prepare Wallet And Deposit
|
||||
${CID} = Create Container ${WALLET} basic_acl=${ACL}
|
||||
|
@ -42,36 +42,41 @@ Check Replication
|
|||
${FILE} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
|
||||
|
||||
${S_OID} = Put Object ${WALLET} ${FILE} ${CID}
|
||||
Validate storage policy for object ${WALLET} ${EXPECTED_COPIES} ${CID} ${S_OID}
|
||||
|
||||
${COPIES} = Get Object Copies Simple ${WALLET} ${CID} ${S_OID}
|
||||
Should Be Equal ${EXPECTED_COPIES} ${COPIES}
|
||||
|
||||
@{NODES_OBJ} = Get nodes with Object ${WALLET} ${CID} ${S_OID}
|
||||
${NODES_LOG_TIME} = Get Nodes Log Latest Timestamp
|
||||
|
||||
@{NODES_OBJ_STOPPED} = Stop nodes 1 @{NODES_OBJ}
|
||||
@{NODES_OBJ_STOPPED} = Stop nodes 1 ${NODES_OBJ}
|
||||
@{NETMAP} = Convert To List ${NEOFS_NETMAP}
|
||||
Remove Values From List ${NETMAP} @{NODES_OBJ_STOPPED}
|
||||
Remove Values From List ${NETMAP} ${NODES_OBJ_STOPPED}
|
||||
|
||||
# We expect that during two epochs the missed copy will be replicated.
|
||||
FOR ${i} IN RANGE 2
|
||||
${COPIES} = Get Object Copies Simple ${WALLET} ${CID} ${S_OID}
|
||||
${PASSED} = Run Keyword And Return Status
|
||||
... Validate storage policy for object ${WALLET} ${EXPECTED_COPIES}
|
||||
... ${CID} ${S_OID} ${EMPTY} ${NETMAP}
|
||||
... Should Be Equal ${EXPECTED_COPIES} ${COPIES}
|
||||
Exit For Loop If ${PASSED}
|
||||
Tick Epoch
|
||||
Sleep ${CHECK_INTERVAL}
|
||||
Sleep ${NEOFS_CONTRACT_CACHE_TIMEOUT}
|
||||
END
|
||||
Run Keyword Unless ${PASSED} Fail Keyword failed: Validate storage policy for object ${S_OID} in container ${CID}
|
||||
Run Keyword Unless ${PASSED} Fail
|
||||
... Storage policy for object ${S_OID} in container ${CID} isn't valid
|
||||
|
||||
Find in Nodes Log object successfully replicated ${NODES_LOG_TIME}
|
||||
Start nodes @{NODES_OBJ_STOPPED}
|
||||
Start nodes ${NODES_OBJ_STOPPED}
|
||||
Tick Epoch
|
||||
|
||||
# We have 2 or 3 copies. Expected behaviour: during two epochs potential 3rd copy should be removed.
|
||||
FOR ${i} IN RANGE 2
|
||||
${COPIES} = Get Object Copies Simple ${WALLET} ${CID} ${S_OID}
|
||||
${PASSED} = Run Keyword And Return Status
|
||||
... Validate storage policy for object ${WALLET} ${EXPECTED_COPIES} ${CID} ${S_OID}
|
||||
... Should Be Equal ${EXPECTED_COPIES} ${COPIES}
|
||||
Exit For Loop If ${PASSED}
|
||||
Tick Epoch
|
||||
Sleep ${CHECK_INTERVAL}
|
||||
Sleep ${NEOFS_CONTRACT_CACHE_TIMEOUT}
|
||||
END
|
||||
Run Keyword Unless ${PASSED} Fail Keyword failed: Validate storage policy for object ${S_OID} in container ${CID}
|
||||
Run Keyword Unless ${PASSED} Fail
|
||||
... Storage policy for object ${S_OID} in container ${CID} isn't valid
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
*** Settings ***
|
||||
Variables common.py
|
||||
|
||||
Library neofs_verbs.py
|
||||
|
||||
Library container.py
|
||||
Library complex_object_actions.py
|
||||
Library neofs.py
|
||||
Library contract_keywords.py
|
||||
Library Collections
|
||||
Library neofs_verbs.py
|
||||
Library neofs.py
|
||||
Library storage_policy.py
|
||||
Library utility_keywords.py
|
||||
|
||||
Library Collections
|
||||
|
||||
Resource setup_teardown.robot
|
||||
Resource payment_operations.robot
|
||||
|
||||
*** Variables ***
|
||||
${CLEANUP_TIMEOUT} = 10s
|
||||
&{FILE_USR_HEADER} = key1=1 key2=abc
|
||||
&{FILE_USR_HEADER_OTH} = key1=2
|
||||
${ALREADY_REMOVED_ERROR} = code = 1024 message = object already removed
|
||||
${ALREADY_REMOVED_ERROR} = code = 2052 message = object already removed
|
||||
|
||||
|
||||
*** Test cases ***
|
||||
|
@ -34,19 +36,13 @@ NeoFS Complex Object Operations
|
|||
|
||||
${S_OID} = Put object ${WALLET} ${FILE} ${CID}
|
||||
${H_OID} = Put object ${WALLET} ${FILE} ${CID} user_headers=${FILE_USR_HEADER}
|
||||
${H_OID_OTH} = Put object ${WALLET} ${FILE} ${CID} user_headers=${FILE_USR_HEADER_OTH}
|
||||
|
||||
Should Be True '${S_OID}'!='${H_OID}' and '${H_OID}'!='${H_OID_OTH}'
|
||||
Should Not Be Equal ${H_OID} ${S_OID}
|
||||
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${S_OID}
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${H_OID}
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${H_OID_OTH}
|
||||
|
||||
@{S_OBJ_ALL} = Create List ${S_OID} ${H_OID} ${H_OID_OTH}
|
||||
@{S_OBJ_H} = Create List ${H_OID}
|
||||
@{S_OBJ_H_OTH} = Create List ${H_OID_OTH}
|
||||
|
||||
Search Object ${WALLET} ${CID} --root expected_objects_list=${S_OBJ_ALL}
|
||||
${COPIES} = Get Complex Object Copies ${WALLET} ${CID} ${S_OID}
|
||||
Should Be Equal As Numbers 2 ${COPIES}
|
||||
${COPIES} = Get Complex Object Copies ${WALLET} ${CID} ${H_OID}
|
||||
Should Be Equal As Numbers 2 ${COPIES}
|
||||
|
||||
${GET_OBJ_S} = Get object ${WALLET} ${CID} ${S_OID}
|
||||
${GET_OBJ_H} = Get object ${WALLET} ${CID} ${H_OID}
|
||||
|
@ -63,9 +59,11 @@ NeoFS Complex Object Operations
|
|||
Get Range ${WALLET} ${CID} ${S_OID} s_get_range ${EMPTY} 0:10
|
||||
Get Range ${WALLET} ${CID} ${H_OID} h_get_range ${EMPTY} 0:10
|
||||
|
||||
@{S_OBJ_ALL} = Create List ${S_OID} ${H_OID}
|
||||
@{S_OBJ_H} = Create List ${H_OID}
|
||||
|
||||
Search object ${WALLET} ${CID} --root expected_objects_list=${S_OBJ_ALL}
|
||||
Search object ${WALLET} ${CID} --root filters=${FILE_USR_HEADER} expected_objects_list=${S_OBJ_H}
|
||||
Search object ${WALLET} ${CID} --root filters=${FILE_USR_HEADER_OTH} expected_objects_list=${S_OBJ_H_OTH}
|
||||
|
||||
&{S_RESPONSE} = Head object ${WALLET} ${CID} ${S_OID}
|
||||
&{H_RESPONSE} = Head object ${WALLET} ${CID} ${H_OID}
|
||||
|
@ -74,9 +72,13 @@ NeoFS Complex Object Operations
|
|||
... ${FILE_USR_HEADER}
|
||||
... msg="There are no User Headers in HEAD response"
|
||||
|
||||
${PAYLOAD_LENGTH} ${SPLIT_ID} ${SPLIT_OBJECTS} = Restore Large Object By Last
|
||||
${PAYLOAD_LENGTH}
|
||||
... ${SPLIT_ID}
|
||||
... ${SPLIT_OBJECTS} = Restore Large Object By Last
|
||||
... ${WALLET} ${CID} ${S_OID}
|
||||
${H_PAYLOAD_LENGTH} ${H_SPLIT_ID} ${H_SPLIT_OBJECTS} = Restore Large Object By Last
|
||||
${H_PAYLOAD_LENGTH}
|
||||
... ${H_SPLIT_ID}
|
||||
... ${H_SPLIT_OBJECTS} = Restore Large Object By Last
|
||||
... ${WALLET} ${CID} ${H_OID}
|
||||
|
||||
Compare With Link Object ${WALLET} ${CID} ${S_OID} ${SPLIT_ID} ${SPLIT_OBJECTS}
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
*** Settings ***
|
||||
Variables common.py
|
||||
|
||||
Library neofs.py
|
||||
Library neofs_verbs.py
|
||||
Library container.py
|
||||
Library contract_keywords.py
|
||||
Library Collections
|
||||
Library neofs.py
|
||||
Library neofs_verbs.py
|
||||
Library storage_policy.py
|
||||
Library utility_keywords.py
|
||||
|
||||
Library Collections
|
||||
|
||||
Resource payment_operations.robot
|
||||
Resource setup_teardown.robot
|
||||
|
||||
*** Variables ***
|
||||
${CLEANUP_TIMEOUT} = 10s
|
||||
&{FILE_USR_HEADER} = key1=1 key2=abc
|
||||
&{FILE_USR_HEADER_OTH} = key1=2
|
||||
|
||||
|
||||
*** Test cases ***
|
||||
|
@ -32,15 +33,14 @@ NeoFS Simple Object Operations
|
|||
|
||||
${S_OID} = Put object ${WALLET} ${FILE} ${CID}
|
||||
${H_OID} = Put object ${WALLET} ${FILE} ${CID} user_headers=${FILE_USR_HEADER}
|
||||
${H_OID_OTH} = Put object ${WALLET} ${FILE} ${CID} user_headers=${FILE_USR_HEADER_OTH}
|
||||
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${S_OID}
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${H_OID}
|
||||
Validate storage policy for object ${WALLET} 2 ${CID} ${H_OID_OTH}
|
||||
${COPIES} = Get Simple Object Copies ${WALLET} ${CID} ${S_OID}
|
||||
Should Be Equal As Numbers 2 ${COPIES}
|
||||
${COPIES} = Get Simple Object Copies ${WALLET} ${CID} ${H_OID}
|
||||
Should Be Equal As Numbers 2 ${COPIES}
|
||||
|
||||
@{S_OBJ_ALL} = Create List ${S_OID} ${H_OID} ${H_OID_OTH}
|
||||
@{S_OBJ_ALL} = Create List ${S_OID} ${H_OID}
|
||||
@{S_OBJ_H} = Create List ${H_OID}
|
||||
@{S_OBJ_H_OTH} = Create List ${H_OID_OTH}
|
||||
|
||||
${GET_OBJ_S} = Get object ${WALLET} ${CID} ${S_OID}
|
||||
${GET_OBJ_H} = Get object ${WALLET} ${CID} ${H_OID}
|
||||
|
@ -59,7 +59,6 @@ NeoFS Simple Object Operations
|
|||
|
||||
Search object ${WALLET} ${CID} expected_objects_list=${S_OBJ_ALL}
|
||||
Search object ${WALLET} ${CID} filters=${FILE_USR_HEADER} expected_objects_list=${S_OBJ_H}
|
||||
Search object ${WALLET} ${CID} filters=${FILE_USR_HEADER_OTH} expected_objects_list=${S_OBJ_H_OTH}
|
||||
|
||||
Head object ${WALLET} ${CID} ${S_OID}
|
||||
&{RESPONSE} = Head object ${WALLET} ${CID} ${H_OID}
|
||||
|
|
Loading…
Reference in a new issue