From 648ed7e63162d9f556a53665a2d705ddae8d234b Mon Sep 17 00:00:00 2001 From: Michael Engel Date: Tue, 5 Sep 2023 17:03:16 +0200 Subject: [PATCH] delegate to bluechi Signed-off-by: Michael Engel --- src/bindings/python/README.md | 46 +- src/bindings/python/bluechi/api.py | 492 ------------------ src/bindings/python/bluechi/ext.py | 92 ---- .../python/{bluechi => pyhirte}/__init__.py | 0 src/bindings/python/setup.py | 23 +- src/bindings/python/setup.py.in | 21 +- 6 files changed, 21 insertions(+), 653 deletions(-) delete mode 100644 src/bindings/python/bluechi/api.py delete mode 100644 src/bindings/python/bluechi/ext.py rename src/bindings/python/{bluechi => pyhirte}/__init__.py (100%) diff --git a/src/bindings/python/README.md b/src/bindings/python/README.md index 42e9a26133..5eb77b6d57 100644 --- a/src/bindings/python/README.md +++ b/src/bindings/python/README.md @@ -1,45 +1,3 @@ -# BlueChi Python bindings +# hirte python bindings -The BlueChi Python bindings provides a Python module to interact with the D-Bus API of BlueChi. It consists of the -following subpackages: - -- `api`: auto-generated code based the BlueChi D-BUS API description -- `ext`: custom written code to simplify common tasks - -## Installation - -Using `pip3`: - -```sh -# from PyPi -pip3 install bluechi -# or from cloned git repo -pip3 install --force dist/bluechi--py3-none-any.whl -``` - -## Examples - -Listing all connected nodes and their current state: - -```python -from bluechi.api import Manager - -for node in Manager().list_nodes(): - # node[name, obj_path, status] - print(f"Node: {node[0]}, State: {node[3]}") -``` - -Starting and stopping of a systemd unit on a specific node using the `Unit` class from the `ext` subpackage to -implicitly wait for the job to finish: - -```python -from bluechi.ext import Unit - -hu = Unit("my-node-name") - -result = hu.start_unit("chronyd.service") -print(result) - -result = hu.stop_unit("chronyd.service") -print(result) -``` +The hirte python bindings are deprecated. Please use [bluechi](https://pypi.org/project/bluechi/) instead. diff --git a/src/bindings/python/bluechi/api.py b/src/bindings/python/bluechi/api.py deleted file mode 100644 index a78becc759..0000000000 --- a/src/bindings/python/bluechi/api.py +++ /dev/null @@ -1,492 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# Generated file. DO NOT EDIT! -# - -from __future__ import annotations - -from typing import Callable, Tuple, Dict, List -from dasbus.typing import ( - Bool, - Double, - Str, - Int, - Byte, - Int16, - UInt16, - Int32, - UInt32, - Int64, - UInt64, - ObjPath, - Structure, -) - -# File has been renamed to UnixFD in following PR included in v1.7 -# https://github.com/rhinstaller/dasbus/pull/70 -try: - from dasbus.typing import File -except ImportError: - from dasbus.typing import UnixFD - -from dasbus.client.proxy import InterfaceProxy, ObjectProxy -from dasbus.connection import MessageBus, SystemMessageBus, SessionMessageBus - -import gi - -gi.require_version("GLib", "2.0") -from gi.repository.GLib import Variant # noqa: E402 - - -BC_DEFAULT_PORT = 842 -BC_DEFAULT_HOST = "127.0.0.1" - -BC_DBUS_INTERFACE = "org.eclipse.bluechi" -BC_OBJECT_PATH = "/org/eclipse/bluechi" -BC_AGENT_DBUS_INTERFACE = "org.eclipse.bluechi.Agent" - - -class ApiBase: - def __init__(self, bus: MessageBus = None, use_systembus=True) -> None: - self.use_systembus = use_systembus - - if bus is not None: - self.bus = bus - elif self.use_systembus: - self.bus = SystemMessageBus() - else: - self.bus = SessionMessageBus() - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - raise Exception("Not implemented!") - - -class Monitor(ApiBase): - def __init__( - self, monitor_path: ObjPath, bus: MessageBus = None, use_systembus=True - ) -> None: - super().__init__(bus, use_systembus) - - self.monitor_path = monitor_path - self.monitor_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.monitor_proxy is None: - self.monitor_proxy = self.bus.get_proxy( - BC_DBUS_INTERFACE, self.monitor_path - ) - - return self.monitor_proxy - - def close(self) -> None: - self.get_proxy().Close() - - def subscribe(self, node: str, unit: str) -> UInt32: - return self.get_proxy().Subscribe( - node, - unit, - ) - - def unsubscribe(self, id: UInt32) -> None: - self.get_proxy().Unsubscribe( - id, - ) - - def subscribe_list(self, node: str, units: List[str]) -> UInt32: - return self.get_proxy().SubscribeList( - node, - units, - ) - - def on_unit_properties_changed( - self, - callback: Callable[ - [ - str, - str, - str, - Structure, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().UnitPropertiesChanged.connect(callback) - - def on_unit_state_changed( - self, - callback: Callable[ - [ - str, - str, - str, - str, - str, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().UnitStateChanged.connect(callback) - - def on_unit_new( - self, - callback: Callable[ - [ - str, - str, - str, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().UnitNew.connect(callback) - - def on_unit_removed( - self, - callback: Callable[ - [ - str, - str, - str, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().UnitRemoved.connect(callback) - - -class Metrics(ApiBase): - def __init__( - self, metrics_path: ObjPath, bus: MessageBus = None, use_systembus=True - ) -> None: - super().__init__(bus, use_systembus) - - self.metrics_path = metrics_path - self.metrics_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.metrics_proxy is None: - self.metrics_proxy = self.bus.get_proxy( - BC_DBUS_INTERFACE, self.metrics_path - ) - - return self.metrics_proxy - - def on_start_unit_job_metrics( - self, - callback: Callable[ - [ - str, - str, - str, - UInt64, - UInt64, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().StartUnitJobMetrics.connect(callback) - - def on_agent_job_metrics( - self, - callback: Callable[ - [ - str, - str, - str, - UInt64, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().AgentJobMetrics.connect(callback) - - -class Job(ApiBase): - def __init__( - self, job_path: ObjPath, bus: MessageBus = None, use_systembus=True - ) -> None: - super().__init__(bus, use_systembus) - - self.job_path = job_path - self.job_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.job_proxy is None: - self.job_proxy = self.bus.get_proxy(BC_DBUS_INTERFACE, self.job_path) - - return self.job_proxy - - def cancel(self) -> None: - self.get_proxy().Cancel() - - @property - def id(self) -> UInt32: - return self.get_proxy().Id - - @property - def node(self) -> str: - return self.get_proxy().Node - - @property - def unit(self) -> str: - return self.get_proxy().Unit - - @property - def job_type(self) -> str: - return self.get_proxy().JobType - - @property - def state(self) -> str: - return self.get_proxy().State - - -class Manager(ApiBase): - def __init__(self, bus: MessageBus = None, use_systembus=True) -> None: - super().__init__(bus, use_systembus) - - self.manager_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.manager_proxy is None: - self.manager_proxy = self.bus.get_proxy(BC_DBUS_INTERFACE, BC_OBJECT_PATH) - - return self.manager_proxy - - def list_units( - self, - ) -> List[Tuple[str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]: - return self.get_proxy().ListUnits() - - def list_nodes(self) -> List[Tuple[str, ObjPath, str]]: - return self.get_proxy().ListNodes() - - def get_node(self, name: str) -> ObjPath: - return self.get_proxy().GetNode( - name, - ) - - def create_monitor(self) -> ObjPath: - return self.get_proxy().CreateMonitor() - - def enable_metrics(self) -> None: - self.get_proxy().EnableMetrics() - - def disable_metrics(self) -> None: - self.get_proxy().DisableMetrics() - - def set_log_level(self, loglevel: str) -> None: - self.get_proxy().SetLogLevel( - loglevel, - ) - - def on_job_new( - self, - callback: Callable[ - [ - UInt32, - ObjPath, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().JobNew.connect(callback) - - def on_job_removed( - self, - callback: Callable[ - [ - UInt32, - ObjPath, - str, - str, - str, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().JobRemoved.connect(callback) - - def on_node_connection_state_changed( - self, - callback: Callable[ - [ - str, - str, - ], - None, - ], - ) -> None: - """ - callback: - """ - self.get_proxy().NodeConnectionStateChanged.connect(callback) - - -class Node(ApiBase): - def __init__( - self, node_name: str, bus: MessageBus = None, use_systembus=True - ) -> None: - super().__init__(bus, use_systembus) - - self.node_name = node_name - self.node_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.node_proxy is None: - manager = self.bus.get_proxy(BC_DBUS_INTERFACE, BC_OBJECT_PATH) - - node_path = manager.GetNode(self.node_name) - self.node_proxy = self.bus.get_proxy(BC_DBUS_INTERFACE, node_path) - - return self.node_proxy - - def start_unit(self, name: str, mode: str) -> ObjPath: - return self.get_proxy().StartUnit( - name, - mode, - ) - - def stop_unit(self, name: str, mode: str) -> ObjPath: - return self.get_proxy().StopUnit( - name, - mode, - ) - - def freeze_unit(self, name: str) -> None: - self.get_proxy().FreezeUnit( - name, - ) - - def thaw_unit(self, name: str) -> None: - self.get_proxy().ThawUnit( - name, - ) - - def reload_unit(self, name: str, mode: str) -> ObjPath: - return self.get_proxy().ReloadUnit( - name, - mode, - ) - - def restart_unit(self, name: str, mode: str) -> ObjPath: - return self.get_proxy().RestartUnit( - name, - mode, - ) - - def get_unit_properties(self, name: str, interface: str) -> Structure: - return self.get_proxy().GetUnitProperties( - name, - interface, - ) - - def get_unit_property(self, name: str, interface: str, property: str) -> Variant: - return self.get_proxy().GetUnitProperty( - name, - interface, - property, - ) - - def set_unit_properties( - self, name: str, runtime: bool, keyvalues: List[Tuple[str, Variant]] - ) -> None: - self.get_proxy().SetUnitProperties( - name, - runtime, - keyvalues, - ) - - def enable_unit_files( - self, files: List[str], runtime: bool, force: bool - ) -> Tuple[bool, List[Tuple[str, str, str]],]: - return self.get_proxy().EnableUnitFiles( - files, - runtime, - force, - ) - - def disable_unit_files( - self, files: List[str], runtime: bool - ) -> List[Tuple[str, str, str]]: - return self.get_proxy().DisableUnitFiles( - files, - runtime, - ) - - def list_units( - self, - ) -> List[Tuple[str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]: - return self.get_proxy().ListUnits() - - def reload(self) -> None: - self.get_proxy().Reload() - - def set_log_level(self, level: str) -> None: - self.get_proxy().SetLogLevel( - level, - ) - - @property - def name(self) -> str: - return self.get_proxy().Name - - @property - def status(self) -> str: - return self.get_proxy().Status - - @property - def last_seen_timestamp(self) -> UInt64: - return self.get_proxy().LastSeenTimestamp - - -class Agent(ApiBase): - def __init__(self, bus: MessageBus = None, use_systembus=True) -> None: - super().__init__(bus, use_systembus) - - self.agent_proxy = None - - def get_proxy(self) -> InterfaceProxy | ObjectProxy: - if self.agent_proxy is None: - self.agent_proxy = self.bus.get_proxy( - BC_AGENT_DBUS_INTERFACE, BC_OBJECT_PATH - ) - - return self.agent_proxy - - def create_proxy(self, local_service_name: str, node: str, unit: str) -> None: - self.get_proxy().CreateProxy( - local_service_name, - node, - unit, - ) - - def remove_proxy(self, local_service_name: str, node: str, unit: str) -> None: - self.get_proxy().RemoveProxy( - local_service_name, - node, - unit, - ) diff --git a/src/bindings/python/bluechi/ext.py b/src/bindings/python/bluechi/ext.py deleted file mode 100644 index f4719dda3e..0000000000 --- a/src/bindings/python/bluechi/ext.py +++ /dev/null @@ -1,92 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -from dasbus.connection import MessageBus -from typing import Callable, List, NamedTuple, Tuple -from collections import namedtuple -from dasbus.loop import EventLoop -from dasbus.typing import UInt32, ObjPath - -from bluechi.api import Node, Manager - - -UnitInfo = namedtuple( - "UnitInfo", - [ - "name", - "description", - "load_state", - "active_state", - "sub_state", - "follower", - "object_path", - "job_id", - "job_type", - "job_object_path", - ], -) - - -UnitChange = namedtuple( - "UnitChange", - [ - "change_type", - "symlink_file", - "symlink_destination", - ], -) - -def unit_changes_from_tuples(tuples: List[Tuple[str, str, str]]) -> List[UnitChange]: - changes: List[UnitChange] = [] - for change in tuples: - changes.append(UnitChange(change[0], change[1], change[2])) - return changes - -EnableUnitsResponse = NamedTuple("EnableUnits", carries_install_info=bool, changes=List[UnitChange]) - - -class Unit: - def __init__( - self, node_name: str, bus: MessageBus = None, use_systembus=True - ) -> None: - self.node = Node(node_name, bus, use_systembus) - self.job_result = "" - - def _wait_for_complete( - self, operation: Callable[[str, str], ObjPath], unit: str - ) -> str: - event_loop = EventLoop() - - def on_job_removed( - _: UInt32, job_path: ObjPath, node_name: str, unit_name: str, result: str - ) -> None: - if job_path == wait_for_job_path: - self.job_result = result - event_loop.quit() - - Manager(bus=self.node.bus).on_job_removed(on_job_removed) - - wait_for_job_path = operation(unit, "replace") - event_loop.run() - - job_result = self.job_result - self.job_result = "" - return job_result - - def start_unit(self, unit: str) -> str: - return self._wait_for_complete(self.node.start_unit, unit) - - def stop_unit(self, unit: str) -> str: - return self._wait_for_complete(self.node.stop_unit, unit) - - def restart_unit(self, unit: str) -> str: - return self._wait_for_complete(self.node.restart_unit, unit) - - def reload_unit(self, unit: str) -> str: - return self._wait_for_complete(self.node.reload_unit, unit) - - def enable_unit_files(self, files: List[str]) -> EnableUnitsResponse: - resp = self.node.enable_unit_files(files, False, False) - return EnableUnitsResponse(resp[0], unit_changes_from_tuples(resp[1])) - - def disable_unit_files(self, files: List[str]) -> List[UnitChange]: - return unit_changes_from_tuples(self.node.disable_unit_files(files, False)) diff --git a/src/bindings/python/bluechi/__init__.py b/src/bindings/python/pyhirte/__init__.py similarity index 100% rename from src/bindings/python/bluechi/__init__.py rename to src/bindings/python/pyhirte/__init__.py diff --git a/src/bindings/python/setup.py b/src/bindings/python/setup.py index e58f3d17d2..33a8d3b95b 100644 --- a/src/bindings/python/setup.py +++ b/src/bindings/python/setup.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later +# SPDX-License-Identifier: GPL-2.0-or-later from setuptools import setup, find_packages @@ -8,22 +8,19 @@ def readme(): setup( - name="bluechi", - version="0.5.0", - description="Python bindings for BlueChi's D-Bus API", + name="pyhirte", + version="0.6.0", + description="Python bindings for hirte's D-Bus API", long_description=readme(), long_description_content_type="text/markdown", - author="BlueChi developers", - url="https://github.com/containers/bluechi/", - license="LGPL-2.1-or-later", - install_requires=[ - "dasbus", - ], - packages=find_packages(), + author="Hirte developers", + url="https://github.com/containers/hirte/", + license="GPL-2.0-or-later", + install_requires=["dasbus", "bluechi"], include_package_data=True, - package_data={"bluechi": ["py.typed"]}, + package_data={"hirte": ["py.typed"]}, zip_safe=True, - keywords=['bluechi', 'python', 'D-Bus', 'systemd'], + keywords=['hirte', 'python', 'D-Bus', 'systemd'], classifiers=[ "Programming Language :: Python", "Programming Language :: Python :: 3", diff --git a/src/bindings/python/setup.py.in b/src/bindings/python/setup.py.in index e38718180a..41fe7a0b10 100644 --- a/src/bindings/python/setup.py.in +++ b/src/bindings/python/setup.py.in @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later +# SPDX-License-Identifier: GPL-2.0-or-later from setuptools import setup, find_packages @@ -8,22 +8,19 @@ def readme(): setup( - name="bluechi", + name="pyhirte", version="@VERSION@", - description="Python bindings for BlueChi's D-Bus API", + description="Python bindings for hirte's D-Bus API", long_description=readme(), long_description_content_type="text/markdown", - author="BlueChi developers", - url="https://github.com/containers/bluechi/", - license="LGPL-2.1-or-later", - install_requires=[ - "dasbus", - ], - packages=find_packages(), + author="Hirte developers", + url="https://github.com/containers/hirte/", + license="GPL-2.0-or-later", + install_requires=["dasbus", "bluechi"], include_package_data=True, - package_data={"bluechi": ["py.typed"]}, + package_data={"hirte": ["py.typed"]}, zip_safe=True, - keywords=['bluechi', 'python', 'D-Bus', 'systemd'], + keywords=['hirte', 'python', 'D-Bus', 'systemd'], classifiers=[ "Programming Language :: Python", "Programming Language :: Python :: 3",