Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions src/stratis_cli/_actions/_bind.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, {})
Expand Down Expand Up @@ -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, {})
Expand Down Expand Up @@ -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, {})
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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

Expand Down
72 changes: 59 additions & 13 deletions src/stratis_cli/_actions/_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -65,34 +66,78 @@
)


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

timeout = get_timeout(
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)

blockdev_spec = ET.fromstring(SPECS[BLOCKDEV_INTERFACE]) # nosec B314
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
Expand Down Expand Up @@ -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
Expand Down
28 changes: 23 additions & 5 deletions src/stratis_cli/_actions/_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -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), {}
Expand Down Expand Up @@ -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, {})
Expand Down Expand Up @@ -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, {})
Expand Down
17 changes: 14 additions & 3 deletions src/stratis_cli/_actions/_list_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
PoolFeature,
SizeTriple,
StoppedPool,
fetch_stopped_pools_property,
)


Expand Down Expand Up @@ -661,8 +660,14 @@ def display(self):
Display info about a stopped pool.
"""

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 = fetch_stopped_pools_property(proxy)
stopped_pools = Manager.Properties.StoppedPools.Get(proxy)
selection_func = self.selection.stopped_pools_func()

stopped_pool = next(
Expand Down Expand Up @@ -699,9 +704,15 @@ def display(self):
"""
List stopped pools.
"""
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 = 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:
Expand Down
Loading
Loading