From 3a93444f1195f27b83d725e9c697ca6f864a8346 Mon Sep 17 00:00:00 2001 From: mulhern Date: Sun, 14 Jan 2024 22:20:50 -0500 Subject: [PATCH] Add filesystem selection in parser Ignore it in listing action, temporarily. Signed-off-by: mulhern --- src/stratis_cli/_actions/_list_filesystem.py | 88 +++++++++++-------- src/stratis_cli/_actions/_logical.py | 17 ++-- src/stratis_cli/_parser/_logical.py | 25 ++++++ .../whitebox/integration/logical/test_list.py | 16 ++++ 4 files changed, 105 insertions(+), 41 deletions(-) diff --git a/src/stratis_cli/_actions/_list_filesystem.py b/src/stratis_cli/_actions/_list_filesystem.py index 5e746e6b2..fac6bb4b1 100644 --- a/src/stratis_cli/_actions/_list_filesystem.py +++ b/src/stratis_cli/_actions/_list_filesystem.py @@ -24,11 +24,56 @@ from ._formatting import TOTAL_USED_FREE, get_property, print_table, size_triple -def list_filesystems(uuid_formatter, *, selection=None): +def list_filesystems( + uuid_formatter, *, pool_name=None, fs_id=None +): # pylint: disable=too-many-locals """ List the specified information about filesystems. """ - klass = List(uuid_formatter, selection=selection) + assert fs_id is None or pool_name is not None + + # pylint: disable=import-outside-toplevel + from ._data import MOFilesystem, MOPool, ObjectManager, filesystems, pools + + proxy = get_object(TOP_OBJECT) + managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) + + if pool_name is not None: + props = {"Name": pool_name} + pool_object_path = next( + pools(props=props).require_unique_match(True).search(managed_objects) + )[0] + fs_props = {"Pool": pool_object_path} | ( + {} if fs_id is None else fs_id.managed_objects_key() + ) + else: + props = None + pool_object_path = None + fs_props = None + + path_to_name = dict( + (path, MOPool(info).Name()) + for path, info in pools(props=props).search(managed_objects) + ) + + filesystems_with_props = [ + MOFilesystem(info) + for objpath, info in filesystems(props=fs_props).search(managed_objects) + ] + + if fs_id is None: + klass = List( + uuid_formatter, + filesystems_with_props, + path_to_name, + ) + else: + klass = List( + uuid_formatter, + filesystems_with_props, + path_to_name, + ) + klass.list_filesystems() @@ -37,17 +82,16 @@ class List: # pylint: disable=too-few-public-methods Handle listing a filesystem or filesystems. """ - def __init__(self, uuid_formatter, *, selection=None): + def __init__(self, uuid_formatter, filesystems_with_props, path_to_name): """ Initialize a List object. :param uuid_formatter: function to format a UUID str or UUID :param uuid_formatter: str or UUID -> str :param bool stopped: whether to list stopped pools - :param selection: how to select the pool to display - :type selection: pair of str * object or NoneType """ self.uuid_formatter = uuid_formatter - self.selection = selection + self.filesystems_with_props = filesystems_with_props + self.path_to_name = path_to_name def list_filesystems(self): """ @@ -69,37 +113,9 @@ def filesystem_size_quartet(dbus_props): limit = get_property(dbus_props.SizeLimit(), Range, None) return f'{size_triple(total, used)} / {"None" if limit is None else limit}' - # pylint: disable=import-outside-toplevel - from ._data import MOFilesystem, MOPool, ObjectManager, filesystems, pools - - proxy = get_object(TOP_OBJECT) - managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) - - props = None if self.selection is None else self.selection.managed_objects_key() - - filesystems_with_props = [ - MOFilesystem(info) - for objpath, info in filesystems( - props=None - if props is None - else { - "Pool": next( - pools(props=props) - .require_unique_match(True) - .search(managed_objects) - )[0] - } - ).search(managed_objects) - ] - - path_to_name = dict( - (path, MOPool(info).Name()) - for path, info in pools(props=props).search(managed_objects) - ) - tables = [ ( - path_to_name[mofilesystem.Pool()], + self.path_to_name[mofilesystem.Pool()], mofilesystem.Name(), filesystem_size_quartet(mofilesystem), date_parser.parse(mofilesystem.Created()) @@ -108,7 +124,7 @@ def filesystem_size_quartet(dbus_props): mofilesystem.Devnode(), self.uuid_formatter(mofilesystem.Uuid()), ) - for mofilesystem in filesystems_with_props + for mofilesystem in self.filesystems_with_props ] print_table( diff --git a/src/stratis_cli/_actions/_logical.py b/src/stratis_cli/_actions/_logical.py index fd91ba59f..859ac888e 100644 --- a/src/stratis_cli/_actions/_logical.py +++ b/src/stratis_cli/_actions/_logical.py @@ -31,7 +31,6 @@ from ._constants import TOP_OBJECT from ._formatting import get_uuid_formatter from ._list_filesystem import list_filesystems -from ._utils import PoolSelector class LogicalActions: @@ -120,15 +119,23 @@ def list_volumes(namespace): """ # This method is invoked as the default for "stratis filesystem"; # these namespace fields may not have been set. - pool_name = getattr(namespace, "pool_name", None) + (pool_name, fs_uuid, fs_name) = ( + getattr(namespace, "pool_name", None), + getattr(namespace, "uuid", None), + getattr(namespace, "name", None), + ) + + assert (fs_name is None and fs_uuid is None) or pool_name is not None uuid_formatter = get_uuid_formatter(namespace.unhyphenated_uuids) - selection = ( - None if pool_name is None else PoolSelector(Id(IdType.NAME, pool_name)) + fs_id = ( + (None if fs_name is None else Id(IdType.NAME, fs_name)) + if fs_uuid is None + else Id(IdType.UUID, fs_uuid) ) - return list_filesystems(uuid_formatter, selection=selection) + return list_filesystems(uuid_formatter, pool_name=pool_name, fs_id=fs_id) @staticmethod def destroy_volumes(namespace): diff --git a/src/stratis_cli/_parser/_logical.py b/src/stratis_cli/_parser/_logical.py index dc483400c..d607800ef 100644 --- a/src/stratis_cli/_parser/_logical.py +++ b/src/stratis_cli/_parser/_logical.py @@ -15,6 +15,9 @@ Definition of filesystem actions to display in the CLI. """ +# isort: STDLIB +from uuid import UUID + from .._actions import LogicalActions from ._debug import FILESYSTEM_DEBUG_SUBCMDS from ._range import RangeAction, RangeActionOrCurrent @@ -69,6 +72,28 @@ "list", { "help": "List filesystems", + "mut_ex_args": [ + ( + False, + [ + ( + "--uuid", + { + "action": "store", + "type": UUID, + "help": "UUID of filesystem to list", + }, + ), + ( + "--name", + { + "action": "store", + "help": "name of filesystem to list", + }, + ), + ], + ), + ], "args": [ ( "pool_name", diff --git a/tests/whitebox/integration/logical/test_list.py b/tests/whitebox/integration/logical/test_list.py index 810168a91..9a6ff3290 100644 --- a/tests/whitebox/integration/logical/test_list.py +++ b/tests/whitebox/integration/logical/test_list.py @@ -175,3 +175,19 @@ def test_list_default(self): command_line = ["--propagate", "fs"] TEST_RUNNER(command_line) + + def test_list_fs_name(self): + """ + Test list with pool and filesystem name. + """ + command_line = self._MENU + [self._POOLNAMES[0], "--name={self._VOLNAMES[0]}"] + TEST_RUNNER(command_line) + + def test_list_fs_name_pool_name_not_match(self): + """ + Test list with pool and filesystem name not coinciding. + """ + command_line = self._MENU + [self._POOLNAMES[1], "--name={self._VOLNAMES[0]}"] + self.check_error( + DbusClientUniqueResultError, command_line, StratisCliErrorCodes.ERROR + )