Skip to content

Commit

Permalink
ftest for daos pool list
Browse files Browse the repository at this point in the history
Skip-NLT: true
Skip-unit-test: true
Quick-functional: true
Test-tag: ListClientPoolsTest
Required-githooks: true
Change-Id: I829dd6e5d26ea8ff3f5c9ff0da758dcc92e90774
Signed-off-by: Michael MacDonald <mjmac@google.com>
  • Loading branch information
mjmac committed Jun 29, 2024
1 parent d147fb3 commit 9900c7d
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 30 deletions.
77 changes: 51 additions & 26 deletions src/tests/ftest/pool/list_pools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
(C) Copyright 2018-2023 Intel Corporation.
(C) Copyright 2018-2024 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
"""
Expand All @@ -9,7 +9,7 @@


class ListPoolsTest(TestWithServers):
"""Test class for dmg pool list tests.
"""Test class for dmg and daos pool list tests.
Test Class Description:
This class contains tests for list pool.
Expand All @@ -20,8 +20,9 @@ class ListPoolsTest(TestWithServers):
def run_case(self, rank_lists, svcn=None):
"""Run test case.
Create pools, call dmg pool list to get the list, and compare against
the UUIDs and service replicas returned at create time.
Create pools, then verify that both dmg and daos tools are able to
list the pools with the same information that was returned when the
pools were created.
Args:
rank_lists (list): Rank lists. List of list of int.
Expand All @@ -35,47 +36,71 @@ def run_case(self, rank_lists, svcn=None):
# Iterate rank lists to create pools. Store the created pool information
# as a dictionary of pool UUID keys with a service replica list value.
self.pool = []
expected_uuids = {}
expected_admin_uuids = {}
for rank_list in rank_lists:
self.pool.append(self.get_pool(target_list=rank_list, svcn=svcn))
expected_uuids[self.pool[-1].uuid.lower()] = self.pool[-1].svc_ranks

# Verify the 'dmg pool info' command lists the correct created pool
# information. The DmgCommand.pool_info() method returns the command
# output as a dictionary of pool UUID keys with service replica list
# values.
detected_uuids = {}
expected_admin_uuids[self.pool[-1].uuid.lower()] = self.pool[-1].svc_ranks

# Remove the default ACLs that allow the creator to access the pool.
# These ACLs don't apply to dmg, but do apply to users.
offlimits = self.pool[0]
self.get_dmg_command().pool_delete_acl(offlimits.uuid, 'OWNER@')
self.get_dmg_command().pool_delete_acl(offlimits.uuid, 'GROUP@')
expected_user_uuids = expected_admin_uuids.copy()
del expected_user_uuids[offlimits.uuid.lower()]

# Verify the 'dmg pool list' command lists the correct created pool
# information.
detected_admin_uuids = {}
try:
for data in self.get_dmg_command().get_pool_list_all():
detected_uuids[data["uuid"]] = data["svc_reps"]
detected_admin_uuids[data["uuid"]] = data["svc_reps"]
except KeyError as error:
self.fail("Error parsing dmg pool list output: {}".format(error))

self.log.info("Expected pool info: %s", str(expected_uuids))
self.log.info("Detected pool info: %s", str(detected_uuids))

# Destroy all the pools
if self.destroy_pools(self.pool):
self.fail("Error destroying pools")
self.pool = []
self.log.info("Expected admin pool info: %s", str(expected_admin_uuids))
self.log.info("Detected admin pool info: %s", str(detected_admin_uuids))

# Compare the expected and detected pool information
self.assertEqual(
expected_uuids, detected_uuids,
expected_admin_uuids, detected_admin_uuids,
"dmg pool info does not list all expected pool UUIDs and their "
"service replicas")

# Verify the 'daos pool list' command lists the correct created pool
# information.
detected_user_uuids = {}
try:
for data in self.get_daos_command().get_pool_list_all():
detected_user_uuids[data["uuid"]] = data["svc_reps"]
except KeyError as error:
self.fail("Error parsing dmg pool list output: {}".format(error))

self.log.info("Expected user pool info: %s", str(expected_user_uuids))
self.log.info("Detected user pool info: %s", str(detected_user_uuids))

# Compare the expected and detected pool information
self.assertEqual(
expected_user_uuids, detected_user_uuids,
"daos pool info does not list all expected pool UUIDs and their "
"service replicas")

# Destroy all the pools
if self.destroy_pools(self.pool):
self.fail("Error destroying pools")
self.pool = []

def test_list_pools(self):
"""JIRA ID: DAOS-3459.
"""JIRA ID: DAOS-3459, DAOS-16038.
Test Description:
Create pools in different ranks, call dmg pool list and verify the
output list matches the output returned when the pools were
created.
Create pools in different ranks, then verify that both dmg and
daos tools are able to list the pools and that the listed output
matches what was returned when the pools were created.
:avocado: tags=all,full_regression
:avocado: tags=vm
:avocado: tags=pool
:avocado: tags=pool,daos_cmd
:avocado: tags=list_pools,test_list_pools
"""
ranks = list(range(len(self.hostlist_servers)))
Expand Down
6 changes: 5 additions & 1 deletion src/tests/ftest/util/command_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,11 @@ def set_command(self, sub_command_list=None, **kwargs):
if sub_command_list is not None:
for sub_command in sub_command_list:
full_command.set_sub_command(sub_command)
full_command = full_command.sub_command_class

if full_command.sub_command_class is not None:
full_command = full_command.sub_command_class
else:
raise CommandFailure(f"invalid sub command: {sub_command}")

# Update any argument values for the full command
full_command.update_params(**kwargs)
Expand Down
107 changes: 107 additions & 0 deletions src/tests/ftest/util/daos_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,113 @@ def pool_list_attrs(self, pool, sys_name=None, verbose=False):
("pool", "list-attrs"), pool=pool, sys_name=sys_name,
verbose=verbose)

def pool_list_containers(self, pool, sys_name=None):
"""List containers in the pool.
Args:
pool (str): pool label or UUID
sys_name (str): DAOS system name. Defaults to None.
Returns:
dict: JSON output
Raises:
CommandFailure: if the daos pool list-containers command fails.
"""
return self._get_json_result(
("pool", "list-containers"), pool=pool, sys_name=sys_name)

def pool_list(self, no_query=False, verbose=False):
"""List pools.
Args:
no_query (bool, optional): If True, do not query for pool stats.
verbose (bool, optional): If True, use verbose mode.
Raises:
CommandFailure: if the daos pool list command fails.
Returns:
dict: the daos json command output converted to a python dictionary
"""
# Sample verbose JSON Output:
# {
# "response": {
# "status": 0,
# "pools": [
# {
# "uuid": "517217db-47c4-4bb9-aae5-e38ca7b3dafc",
# "label": "mkp1",
# "svc_reps": [
# 0
# ],
# "total_targets": 8,
# "disabled_targets": 0,
# "usage": [
# {
# "tier_name": "SCM",
# "size": 3000000000,
# "free": 2995801112,
# "imbalance": 0
# },
# {
# "tier_name": "NVME",
# "size": 47000000000,
# "free": 26263322624,
# "imbalance": 36
# }
# ]
# }
# ]
# },
# "error": null,
# "status": 0
# }
return self._get_json_result(
("pool", "list"), no_query=no_query, verbose=verbose)

def _parse_pool_list(self, key=None, **kwargs):
"""Parse the daos pool list json output for the requested information.
Args:
key (str, optional): pool list json dictionary key in
["response"]["pools"]. Defaults to None.
Raises:
CommandFailure: if the daos pool list command fails.
Returns:
list: list of all the pool items in the daos pool list json output
for the requested json dictionary key. This will be an empty
list if the key does not exist or the json output was not in
the expected format.
"""
pool_list = self.pool_list(**kwargs)
try:
if pool_list["response"]["pools"] is None:
return []
if key:
return [pool[key] for pool in pool_list["response"]["pools"]]
return pool_list["response"]["pools"]
except KeyError:
return []

def get_pool_list_all(self, **kwargs):
"""Get a list of all the pool information from daos pool list.
Raises:
CommandFailure: if the daos pool list command fails.
Returns:
list: a list of dictionaries containing information for each pool
from the daos pool list json output
"""
return self._parse_pool_list(**kwargs)

def container_query(self, pool, cont, sys_name=None):
"""Query a container.
Expand Down
18 changes: 15 additions & 3 deletions src/tests/ftest/util/daos_utils_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
(C) Copyright 2020-2023 Intel Corporation.
(C) Copyright 2020-2024 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
"""
Expand Down Expand Up @@ -47,8 +47,10 @@ def __init__(self):

def get_sub_command_class(self):
# pylint: disable=redefined-variable-type
"""Get the dmg network sub command object."""
if self.sub_command.value in ("list-containers", "list"):
"""Get the daos pool sub command object."""
if self.sub_command.value == "list":
self.sub_command_class = self.ListSubCommand()
elif self.sub_command.value == "list-containers":
self.sub_command_class = self.ListContainersSubCommand()
elif self.sub_command.value == "query":
self.sub_command_class = self.QuerySubCommand()
Expand All @@ -65,6 +67,16 @@ def get_sub_command_class(self):
else:
self.sub_command_class = None

class ListSubCommand(CommandWithParameters):
"""Defines an object for the daos pool list command."""

def __init__(self):
"""Create a daos pool list command object."""
super().__init__("/run/daos/pool/list/*", "list")
self.sys_name = FormattedParameter("--sys-name={}")
self.no_query = FormattedParameter("--no-query", False)
self.verbose = FormattedParameter("--verbose", False)

class CommonPoolSubCommand(CommandWithParameters):
"""Defines an object for the common daos pool sub-command.
Expand Down

0 comments on commit 9900c7d

Please sign in to comment.