From fd7a778c3afd840f2df2aee075a1266cd8dc24b3 Mon Sep 17 00:00:00 2001 From: mulhern Date: Fri, 16 Jan 2026 14:49:18 -0500 Subject: [PATCH 1/2] Remove fetch_stopped_pools_property method Signed-off-by: mulhern --- src/stratis_cli/_actions/_list_pool.py | 9 ++++++--- src/stratis_cli/_actions/_pool.py | 4 ++-- src/stratis_cli/_actions/_utils.py | 16 ---------------- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/stratis_cli/_actions/_list_pool.py b/src/stratis_cli/_actions/_list_pool.py index a60f26066..073af7e77 100644 --- a/src/stratis_cli/_actions/_list_pool.py +++ b/src/stratis_cli/_actions/_list_pool.py @@ -46,7 +46,6 @@ PoolFeature, SizeTriple, StoppedPool, - fetch_stopped_pools_property, ) @@ -661,8 +660,10 @@ def display(self): Display info about a stopped pool. """ + from ._data import Manager # pylint: disable=import-outside-toplevel + proxy = get_object(TOP_OBJECT) - stopped_pools = fetch_stopped_pools_property(proxy) + stopped_pools = Manager.Properties.StoppedPools.Get(proxy) selection_func = self.selection.stopped_pools_func() stopped_pool = next( @@ -699,9 +700,11 @@ def display(self): """ List stopped pools. """ + from ._data import Manager # pylint: disable=import-outside-toplevel + proxy = get_object(TOP_OBJECT) - stopped_pools = fetch_stopped_pools_property(proxy) + stopped_pools = Manager.Properties.StoppedPools.Get(proxy) def clevis_str(value, metadata_version, features): if metadata_version is MetadataVersion.V2: diff --git a/src/stratis_cli/_actions/_pool.py b/src/stratis_cli/_actions/_pool.py index 331900ba9..9b687611a 100644 --- a/src/stratis_cli/_actions/_pool.py +++ b/src/stratis_cli/_actions/_pool.py @@ -51,7 +51,7 @@ from ._constants import TOP_OBJECT from ._formatting import get_property, get_uuid_formatter from ._list_pool import list_pools -from ._utils import StoppedPool, fetch_stopped_pools_property, get_passphrase_fd +from ._utils import StoppedPool, get_passphrase_fd def _generate_pools_to_blockdevs( @@ -308,7 +308,7 @@ def start_pool(namespace: Namespace): elif namespace.unlock_method is UnlockMethod.ANY: unlock_method = (True, (False, 0)) else: - stopped_pools = fetch_stopped_pools_property(proxy) + stopped_pools = Manager.Properties.StoppedPools.Get(proxy) selection_func = pool_id.stopped_pools_func() stopped_pool = next( ( diff --git a/src/stratis_cli/_actions/_utils.py b/src/stratis_cli/_actions/_utils.py index d2c01e0e5..32b081baa 100644 --- a/src/stratis_cli/_actions/_utils.py +++ b/src/stratis_cli/_actions/_utils.py @@ -28,7 +28,6 @@ # isort: THIRDPARTY from dbus import Dictionary, Struct -from dbus.proxies import ProxyObject from justbytes import Range from .._errors import ( @@ -254,21 +253,6 @@ def get_passphrase_fd(*, keyfile_path=None, verify=True) -> Tuple[int, int]: return (file_desc, fd_to_close) -def fetch_stopped_pools_property(proxy: ProxyObject) -> Dictionary: - """ - Fetch the StoppedPools property from stratisd. - :param proxy: proxy to the top object in stratisd - :return: a representation of stopped devices - :rtype: dict - :raises StratisCliEngineError: - """ - - # pylint: disable=import-outside-toplevel - from ._data import Manager - - return Manager.Properties.StoppedPools.Get(proxy) - - class SizeTriple: """ Manage values in a size triple. From d57efb82160addc332199204f94ad398b10561fc Mon Sep 17 00:00:00 2001 From: mulhern Date: Fri, 16 Jan 2026 15:05:23 -0500 Subject: [PATCH 2/2] Add a make_partial_class method Signed-off-by: mulhern --- src/stratis_cli/_actions/_bind.py | 45 +++++++-- src/stratis_cli/_actions/_data.py | 72 +++++++++++--- src/stratis_cli/_actions/_debug.py | 28 +++++- src/stratis_cli/_actions/_list_pool.py | 12 ++- src/stratis_cli/_actions/_logical.py | 92 +++++++++++++++--- src/stratis_cli/_actions/_pool.py | 128 ++++++++++++++++++++----- src/stratis_cli/_actions/_stratis.py | 6 +- src/stratis_cli/_actions/_top.py | 38 ++++++-- tests/_misc.py | 10 +- tests/integration/test_stratis.py | 32 ------- 10 files changed, 357 insertions(+), 106 deletions(-) diff --git a/src/stratis_cli/_actions/_bind.py b/src/stratis_cli/_actions/_bind.py index 66f005cc1..9445c53f9 100644 --- a/src/stratis_cli/_actions/_bind.py +++ b/src/stratis_cli/_actions/_bind.py @@ -54,8 +54,15 @@ def bind_clevis(namespace: Namespace): discussion of the pin and the configuration, consult Clevis documentation. """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["BindClevis"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -90,8 +97,15 @@ def bind_keyring(namespace: Namespace): """ Bind all devices in an encrypted pool using the kernel keyring. """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["BindKeyring"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -126,7 +140,11 @@ def unbind(namespace: Namespace): :raises StratisCliEngineError: """ # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import POOL_GEN, ObjectManager, pools + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["UnbindClevis", "UnbindKeyring"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -173,8 +191,15 @@ def rebind_clevis(namespace: Namespace): """ Rebind with Clevis nbde/tang """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["RebindClevis"], properties=[] + ) pool_id = _get_pool_id(namespace) @@ -211,7 +236,11 @@ def rebind_keyring(namespace: Namespace): Rebind with a kernel keyring """ # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import POOL_GEN, ObjectManager, pools + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["RebindKeyring"], properties=[] + ) keydesc = namespace.keydesc diff --git a/src/stratis_cli/_actions/_data.py b/src/stratis_cli/_actions/_data.py index b484fb0f6..ad52d51c0 100644 --- a/src/stratis_cli/_actions/_data.py +++ b/src/stratis_cli/_actions/_data.py @@ -18,6 +18,7 @@ import os import sys import xml.etree.ElementTree as ET # nosec B405 +from typing import List, Optional, Type # isort: FIRSTPARTY from dbus_client_gen import ( @@ -65,6 +66,59 @@ ) +class DbusClassGen: # pylint: disable=too-few-public-methods + """ + Instructions for making a dbus-python class for calling D-Bus methods. + """ + + def __init__(self, name: str, interface_name: str): + """ + Initializer. + """ + self.name = name + self.interface_name = interface_name + + def make_partial_class( + self, + *, + methods: Optional[List[str]] = None, + properties: Optional[List[str]] = None, + timeout: int = DBUS_TIMEOUT_SECONDS, # pylint: disable=redefined-outer-name + ) -> Type: + """ + Make a class from a spec with only requested methods and properties. + + Interpret None as meaning include all, [] as meaning include none. + """ + timeout = get_timeout(os.environ.get("STRATIS_DBUS_TIMEOUT", timeout * 1000)) + + spec = ET.fromstring(SPECS[self.interface_name]) # nosec B314 + + new_spec = ET.Element(spec.tag, spec.attrib) + new_spec.extend( + [ + child + for child in spec + if child.tag == "method" + and (methods is None or child.get("name") in methods) + ] + ) + new_spec.extend( + [ + child + for child in spec + if child.tag == "property" + and (properties is None or child.get("name") in properties) + ] + ) + return make_class(self.name, new_spec, timeout=timeout) + + +REPORT_GEN = DbusClassGen("Report", REPORT_INTERFACE) +FILESYSTEM_GEN = DbusClassGen("Filesystem", FILESYSTEM_INTERFACE) +MANAGER_GEN = DbusClassGen("Manager", MANAGER_INTERFACE) +POOL_GEN = DbusClassGen("Pool", POOL_INTERFACE) + try: # pylint: disable=invalid-name @@ -72,16 +126,11 @@ os.environ.get("STRATIS_DBUS_TIMEOUT", DBUS_TIMEOUT_SECONDS * 1000) ) - report_spec = ET.fromstring(SPECS[REPORT_INTERFACE]) # nosec B314 - Report = make_class("Report", report_spec, timeout) - filesystem_spec = ET.fromstring(SPECS[FILESYSTEM_INTERFACE]) # nosec B314 - Filesystem = make_class("Filesystem", filesystem_spec, timeout) MOFilesystem = managed_object_class("MOFilesystem", filesystem_spec) filesystems = mo_query_builder(filesystem_spec) pool_spec = ET.fromstring(SPECS[POOL_INTERFACE]) # nosec B314 - Pool = make_class("Pool", pool_spec, timeout) MOPool = managed_object_class("MOPool", pool_spec) pools = mo_query_builder(pool_spec) @@ -89,10 +138,6 @@ MODev = managed_object_class("MODev", blockdev_spec) devs = mo_query_builder(blockdev_spec) - Manager = make_class( - "Manager", ET.fromstring(SPECS[MANAGER_INTERFACE]), timeout # nosec B314 - ) - ObjectManager = make_class( "ObjectManager", ET.fromstring(SPECS["org.freedesktop.DBus.ObjectManager"]), # nosec B314 @@ -142,10 +187,11 @@ def new_method(proxy, args): try: - _add_abs_path_assertion(Manager, "CreatePool", "devices") - _add_abs_path_assertion(Pool, "InitCache", "devices") - _add_abs_path_assertion(Pool, "AddCacheDevs", "devices") - _add_abs_path_assertion(Pool, "AddDataDevs", "devices") + # _add_abs_path_assertion(Manager, "CreatePool", "devices") + # _add_abs_path_assertion(Pool, "InitCache", "devices") + # _add_abs_path_assertion(Pool, "AddCacheDevs", "devices") + # _add_abs_path_assertion(Pool, "AddDataDevs", "devices") + pass except AttributeError as err: # pragma: no cover # This can only happen if the expected method is missing from the XML spec diff --git a/src/stratis_cli/_actions/_debug.py b/src/stratis_cli/_actions/_debug.py index 378cfbfa5..33db2d871 100644 --- a/src/stratis_cli/_actions/_debug.py +++ b/src/stratis_cli/_actions/_debug.py @@ -37,7 +37,11 @@ def refresh_state(_namespace: Namespace): """ Refresh pools from their metadata up. """ - from ._data import Manager # pylint: disable=import-outside-toplevel + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["RefreshState"], properties=[] + ) (return_code, message) = Manager.Methods.RefreshState( get_object(TOP_OBJECT), {} @@ -98,8 +102,15 @@ def get_metadata(namespace: Namespace): """ Get some information about the pool-level metadata. """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["Metadata"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -161,8 +172,15 @@ def get_metadata(namespace: Namespace): :raises StratisCliEngineError: """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["FilesystemMetadata"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) diff --git a/src/stratis_cli/_actions/_list_pool.py b/src/stratis_cli/_actions/_list_pool.py index 073af7e77..d255587fd 100644 --- a/src/stratis_cli/_actions/_list_pool.py +++ b/src/stratis_cli/_actions/_list_pool.py @@ -660,7 +660,11 @@ def display(self): Display info about a stopped pool. """ - from ._data import Manager # pylint: disable=import-outside-toplevel + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["StoppedPools"] + ) proxy = get_object(TOP_OBJECT) stopped_pools = Manager.Properties.StoppedPools.Get(proxy) @@ -700,7 +704,11 @@ def display(self): """ List stopped pools. """ - from ._data import Manager # pylint: disable=import-outside-toplevel + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["StoppedPools"] + ) proxy = get_object(TOP_OBJECT) diff --git a/src/stratis_cli/_actions/_logical.py b/src/stratis_cli/_actions/_logical.py index c67defbfc..40586158f 100644 --- a/src/stratis_cli/_actions/_logical.py +++ b/src/stratis_cli/_actions/_logical.py @@ -52,8 +52,17 @@ def create_volumes(namespace: Namespace): """ # pylint: disable=too-many-locals - # pylint: disable=import-outside-toplevel - from ._data import MOFilesystem, ObjectManager, Pool, filesystems, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["CreateFilesystems"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -150,8 +159,17 @@ def destroy_volumes(namespace: Namespace): """ # pylint: disable=too-many-locals - # pylint: disable=import-outside-toplevel - from ._data import MOFilesystem, ObjectManager, Pool, filesystems, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["DestroyFilesystems"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -212,8 +230,16 @@ def snapshot_filesystem(namespace: Namespace): :raises StratisCliEngineError: :raises StratisCliNoChangeError: """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, filesystems, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + filesystems, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["SnapshotFilesystem"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -249,7 +275,11 @@ def rename_fs(namespace: Namespace): :raises StratisCliNoChangeError: """ # pylint: disable=import-outside-toplevel - from ._data import Filesystem, ObjectManager, filesystems, pools + from ._data import FILESYSTEM_GEN, ObjectManager, filesystems, pools + + Filesystem = FILESYSTEM_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["SetName"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -280,7 +310,17 @@ def set_size_limit(namespace: Namespace): # pylint: disable=too-many-locals Set an upper limit on the size of the filesystem. """ # pylint: disable=import-outside-toplevel - from ._data import Filesystem, MOFilesystem, ObjectManager, filesystems, pools + from ._data import ( + FILESYSTEM_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Filesystem = FILESYSTEM_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["SizeLimit"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -318,7 +358,17 @@ def unset_size_limit(namespace: Namespace): Unset upper limit on the size of the filesystem. """ # pylint: disable=import-outside-toplevel - from ._data import Filesystem, MOFilesystem, ObjectManager, filesystems, pools + from ._data import ( + FILESYSTEM_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Filesystem = FILESYSTEM_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["SizeLimit"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -346,7 +396,17 @@ def schedule_revert(namespace: Namespace): Schedule reverting a snapshot into its origin. """ # pylint: disable=import-outside-toplevel - from ._data import Filesystem, MOFilesystem, ObjectManager, filesystems, pools + from ._data import ( + FILESYSTEM_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Filesystem = FILESYSTEM_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["MergeScheduled"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -378,7 +438,17 @@ def cancel_revert(namespace: Namespace): Cancel reverting a snapshot into its origin. """ # pylint: disable=import-outside-toplevel - from ._data import Filesystem, MOFilesystem, ObjectManager, filesystems, pools + from ._data import ( + FILESYSTEM_GEN, + MOFilesystem, + ObjectManager, + filesystems, + pools, + ) + + Filesystem = FILESYSTEM_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["MergeScheduled"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) diff --git a/src/stratis_cli/_actions/_pool.py b/src/stratis_cli/_actions/_pool.py index 9b687611a..11cbbdee7 100644 --- a/src/stratis_cli/_actions/_pool.py +++ b/src/stratis_cli/_actions/_pool.py @@ -176,8 +176,19 @@ def create_pool(namespace: Namespace): # pylint: disable=too-many-locals :raises StratisCliIncoherenceError: :raises StratisCliNameConflictError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager, ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + MANAGER_GEN, + POOL_GEN, + ObjectManager, + pools, + ) + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["CreatePool"], properties=[] + ) + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["Overprovisioning"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -265,8 +276,11 @@ def stop_pool(namespace: Namespace): :raises StratisCliIncoherenceError: :raises StratisCliEngineError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["StopPool"], properties=[] + ) proxy = get_object(TOP_OBJECT) @@ -291,8 +305,11 @@ def start_pool(namespace: Namespace): :raises StratisCliIncoherenceError: :raises StratisCliEngineError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["StartPool"], properties=["StoppedPools"] + ) proxy = get_object(TOP_OBJECT) @@ -376,8 +393,18 @@ def init_cache(namespace: Namespace): # pylint: disable=too-many-locals :raises StratisCliEngineError: :raises StratisCliIncoherenceError: """ - # pylint: disable=import-outside-toplevel - from ._data import MODev, MOPool, ObjectManager, Pool, devs, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MODev, + MOPool, + ObjectManager, + devs, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["InitCache"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -456,8 +483,15 @@ def destroy_pool(namespace: Namespace): :raises StratisCliEngineError: :raises StratisCliIncoherenceError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager, ObjectManager, pools + from ._data import ( # pylint: disable=import-outside-toplevel + MANAGER_GEN, + ObjectManager, + pools, + ) + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["DestroyPool"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -494,8 +528,15 @@ def rename_pool(namespace: Namespace): :raises StratisCliEngineError: :raises StratisCliNoChangeError: """ - # pylint: disable=import-outside-toplevel - from ._data import ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["SetName"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -526,8 +567,17 @@ def add_data_devices(namespace: Namespace): # pylint: disable=too-many-locals :raises StratisCliInUseSameTierError: :raises StratisCliPartialChangeError: """ - # pylint: disable=import-outside-toplevel - from ._data import MODev, ObjectManager, Pool, devs, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MODev, + ObjectManager, + devs, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["AddDataDevs"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -581,8 +631,17 @@ def add_cache_devices(namespace: Namespace): # pylint: disable=too-many-locals :raises StratisCliInUseSameTierError: :raises StratisCliPartialChangeError: """ - # pylint: disable=import-outside-toplevel - from ._data import MODev, ObjectManager, Pool, devs, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MODev, + ObjectManager, + devs, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["AddCacheDevs"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -635,8 +694,17 @@ def extend_data(namespace: Namespace): # pylint: disable=too-many-locals :raises StratisCliEngineError: :raises StratisCliIncoherenceError: """ - # pylint: disable=import-outside-toplevel - from ._data import MODev, ObjectManager, Pool, devs, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MODev, + ObjectManager, + devs, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["GrowPhysicalDevice"], properties=[] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -753,8 +821,16 @@ def set_fs_limit(namespace: Namespace): """ Set the filesystem limit. """ - # pylint: disable=import-outside-toplevel - from ._data import MOPool, ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MOPool, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["FsLimit"] + ) proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) @@ -776,8 +852,16 @@ def set_overprovisioning_mode(namespace: Namespace): """ Set the overprovisioning mode. """ - # pylint: disable=import-outside-toplevel - from ._data import MOPool, ObjectManager, Pool, pools + from ._data import ( # pylint: disable=import-outside-toplevel + POOL_GEN, + MOPool, + ObjectManager, + pools, + ) + + Pool = POOL_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["Overprovisioning"] + ) decision = bool(namespace.decision) diff --git a/src/stratis_cli/_actions/_stratis.py b/src/stratis_cli/_actions/_stratis.py index 22652bec8..3f5e542d9 100644 --- a/src/stratis_cli/_actions/_stratis.py +++ b/src/stratis_cli/_actions/_stratis.py @@ -33,6 +33,10 @@ def list_stratisd_version(_namespace: Namespace): List the stratisd version. """ # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=[], properties=["Version"] + ) print(f"{Manager.Properties.Version.Get(get_object(TOP_OBJECT))}") diff --git a/src/stratis_cli/_actions/_top.py b/src/stratis_cli/_actions/_top.py index b918cc71f..0eb03723b 100644 --- a/src/stratis_cli/_actions/_top.py +++ b/src/stratis_cli/_actions/_top.py @@ -48,8 +48,11 @@ def _fetch_keylist(proxy: ProxyObject) -> Array: :rtype: list of str :raises StratisCliEngineError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["ListKeys"], properties=[] + ) (keys, return_code, message) = Manager.Methods.ListKeys(proxy, {}) if return_code != StratisdErrors.OK: # pragma: no cover @@ -76,8 +79,11 @@ def _add_update_key( fd_argument, fd_to_close = get_passphrase_fd(keyfile_path=keyfile_path) - # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["SetKey"], properties=[] + ) add_ret = Manager.Methods.SetKey( proxy, @@ -102,9 +108,8 @@ def get_report(namespace: Namespace): :raises StratisCliEngineError: """ - # pylint: disable=import-outside-toplevel if namespace.report_name is ReportKey.MANAGED_OBJECTS: - from ._data import ObjectManager + from ._data import ObjectManager # pylint: disable=import-outside-toplevel dbus_report: Dictionary = ObjectManager.Methods.GetManagedObjects( get_object(TOP_OBJECT), {} @@ -120,14 +125,24 @@ def get_report(namespace: Namespace): else: if namespace.report_name is ReportKey.ENGINE_STATE: - from ._data import Manager + from ._data import ( # pylint: disable=import-outside-toplevel + MANAGER_GEN, + ) + + Manager = ( # pylint: disable=invalid-name + MANAGER_GEN.make_partial_class( + methods=["EngineStateReport"], properties=[] + ) + ) (json_report, return_code, message) = Manager.Methods.EngineStateReport( get_object(TOP_OBJECT), {} ) else: - from ._data import Report + from ._data import REPORT_GEN # pylint: disable=import-outside-toplevel + + Report = REPORT_GEN.make_partial_class() # pylint: disable=invalid-name (json_report, return_code, message) = Report.Methods.GetReport( get_object(TOP_OBJECT), {"name": str(namespace.report_name)} @@ -239,8 +254,11 @@ def unset_key(namespace: Namespace): :raises StratisCliNoChangeError: :raises StratisCliIncoherenceError: """ - # pylint: disable=import-outside-toplevel - from ._data import Manager + from ._data import MANAGER_GEN # pylint: disable=import-outside-toplevel + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["UnsetKey"], properties=[] + ) proxy = get_object(TOP_OBJECT) diff --git a/tests/_misc.py b/tests/_misc.py index 0a7f38a41..455ad334a 100644 --- a/tests/_misc.py +++ b/tests/_misc.py @@ -394,9 +394,15 @@ def stop_pool(pool_name): :raises: RuntimeError """ - # pylint: disable=import-outside-toplevel # isort: LOCAL - from stratis_cli._actions._data import Manager + # pylint: disable=import-outside-toplevel + from stratis_cli._actions._data import ( + MANAGER_GEN, + ) + + Manager = MANAGER_GEN.make_partial_class( # pylint: disable=invalid-name + methods=["StopPool"], properties=[] + ) proxy = get_object(TOP_OBJECT) diff --git a/tests/integration/test_stratis.py b/tests/integration/test_stratis.py index 1b727b55d..e879733de 100644 --- a/tests/integration/test_stratis.py +++ b/tests/integration/test_stratis.py @@ -25,7 +25,6 @@ from dbus_python_client_gen import ( DPClientGetPropertyContext, DPClientInvocationError, - DPClientMethodCallContext, ) # isort: LOCAL @@ -137,37 +136,6 @@ def Get(_): # pylint: disable=invalid-name, no-method-argument ): self.check_error(DPClientInvocationError, command_line, _ERROR) - def test_dbus_action_method_not_return(self): - """ - Verify behavior of stratisd ListKeys method result not obtained in - reasonable time. Fake the correct D-Bus exception. - """ - # pylint: disable=import-outside-toplevel - command_line = ["--propagate", "key", "list"] - - # isort: LOCAL - from stratis_cli._actions import _data - - class _KeyLister: # pylint: disable=too-few-public-methods - @staticmethod - def ListKeys( - _object, _args - ): # pylint: disable=invalid-name, no-method-argument - """ - Mock ListKeys method. - """ - dbus_exception = dbus.exceptions.DBusException("msg") - dbus_exception._dbus_error_name = "org.freedesktop.DBus.Error.NoReply" # pylint: disable=protected-access - raise DPClientInvocationError( - "fake timeout error", - "intf", - DPClientMethodCallContext("ListKeys", []), - ) from dbus_exception - - # pylint: disable=protected-access - with patch.object(_data.Manager.Methods, "ListKeys", _KeyLister.ListKeys): - self.check_error(DPClientInvocationError, command_line, _ERROR) - class KeyboardInterruptTestCase(SimTestCase): """