Temporarily reintroduce the safe_dbus module
Related: RHEL-115005
This commit is contained in:
parent
afd7d00240
commit
e6a6ef67b7
252
0002-Temporarily-reintroduce-the-safe_dbus-module.patch
Normal file
252
0002-Temporarily-reintroduce-the-safe_dbus-module.patch
Normal file
@ -0,0 +1,252 @@
|
||||
From 3a35d48fb823bae87d044234b199e1dde64e7666 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Wed, 29 Oct 2025 11:00:41 +0100
|
||||
Subject: [PATCH] Temporarily reintroduce the safe_dbus module
|
||||
|
||||
Anaconda imports SafeDBusError from this and doing a joint release
|
||||
in RHEL would be too complicated.
|
||||
|
||||
Related: RHEL-115005
|
||||
---
|
||||
blivet/safe_dbus.py | 229 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 229 insertions(+)
|
||||
create mode 100644 blivet/safe_dbus.py
|
||||
|
||||
diff --git a/blivet/safe_dbus.py b/blivet/safe_dbus.py
|
||||
new file mode 100644
|
||||
index 00000000..1bade46b
|
||||
--- /dev/null
|
||||
+++ b/blivet/safe_dbus.py
|
||||
@@ -0,0 +1,229 @@
|
||||
+#
|
||||
+# Copyright (C) 2013-2015 Red Hat, Inc.
|
||||
+#
|
||||
+# This copyrighted material is made available to anyone wishing to use,
|
||||
+# modify, copy, or redistribute it subject to the terms and conditions of
|
||||
+# the GNU General Public License v.2, or (at your option) any later version.
|
||||
+# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
+# ANY WARRANTY expressed or implied, including the implied warranties of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
+# Public License for more details. You should have received a copy of the
|
||||
+# GNU General Public License along with this program; if not, write to the
|
||||
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
||||
+# source code or documentation are not subject to the GNU General Public
|
||||
+# License and may only be used or replicated with the express permission of
|
||||
+# Red Hat, Inc.
|
||||
+#
|
||||
+# Red Hat Author(s): Vratislav Podzimek <vpodzime@redhat.com>
|
||||
+#
|
||||
+# This module was taken from the sources of the Anaconda installer.
|
||||
+#
|
||||
+
|
||||
+"""Module providing thread-safe and mainloop-safe DBus operations."""
|
||||
+
|
||||
+import gi
|
||||
+gi.require_version("GLib", "2.0")
|
||||
+gi.require_version("Gio", "2.0")
|
||||
+
|
||||
+from gi.repository import GLib, Gio
|
||||
+
|
||||
+import os
|
||||
+
|
||||
+DEFAULT_DBUS_TIMEOUT = -1
|
||||
+DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
|
||||
+DBUS_INTRO_IFACE = "org.freedesktop.DBus.Introspectable"
|
||||
+
|
||||
+
|
||||
+class SafeDBusError(Exception):
|
||||
+ """Class for exceptions defined in this module."""
|
||||
+
|
||||
+
|
||||
+class DBusCallError(SafeDBusError):
|
||||
+ """Class for the errors related to calling methods over DBus."""
|
||||
+
|
||||
+
|
||||
+class DBusPropertyError(DBusCallError):
|
||||
+ """Class for the errors related to getting property values over DBus."""
|
||||
+
|
||||
+
|
||||
+def get_new_system_connection():
|
||||
+ """Return a new connection to the system bus."""
|
||||
+
|
||||
+ return Gio.DBusConnection.new_for_address_sync(
|
||||
+ Gio.dbus_address_get_for_bus_sync(Gio.BusType.SYSTEM, None),
|
||||
+ Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT |
|
||||
+ Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION,
|
||||
+ None, None)
|
||||
+
|
||||
+
|
||||
+def get_new_session_connection():
|
||||
+ """
|
||||
+ Get a connection handle for the per-user-login-session message bus.
|
||||
+
|
||||
+ !!! RUN THIS EARLY !!! like, before any other threads start. Connections to
|
||||
+ the session bus must be made with the effective UID of the login user,
|
||||
+ which in live installs is not the UID of anaconda. This means we need to
|
||||
+ call seteuid in this method, and doing that after threads have started will
|
||||
+ probably do something weird.
|
||||
+
|
||||
+ Live installs use consolehelper to run as root, which sets the original
|
||||
+ UID in $USERHELPER_UID.
|
||||
+
|
||||
+ :return: the session connection handle
|
||||
+ :rtype: Gio.DBusConnection
|
||||
+ :raise DBusCallError: if some DBus related error appears
|
||||
+ :raise OSError: if unable to set the effective UID
|
||||
+ """
|
||||
+
|
||||
+ old_euid = None
|
||||
+ if "USERHELPER_UID" in os.environ:
|
||||
+ old_euid = os.geteuid()
|
||||
+ os.seteuid(int(os.environ["USERHELPER_UID"]))
|
||||
+
|
||||
+ try:
|
||||
+ connection = Gio.DBusConnection.new_for_address_sync(
|
||||
+ Gio.dbus_address_get_for_bus_sync(Gio.BusType.SESSION, None),
|
||||
+ Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT |
|
||||
+ Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION,
|
||||
+ None, None)
|
||||
+ except GLib.GError as gerr:
|
||||
+ raise DBusCallError("Unable to connect to session bus: %s" % gerr)
|
||||
+ finally:
|
||||
+ if old_euid is not None:
|
||||
+ os.seteuid(old_euid)
|
||||
+
|
||||
+ if connection.is_closed():
|
||||
+ raise DBusCallError("Connection is closed")
|
||||
+
|
||||
+ return connection
|
||||
+
|
||||
+
|
||||
+def call_sync(service, obj_path, iface, method, args,
|
||||
+ connection=None, fds=None, timeout=DEFAULT_DBUS_TIMEOUT):
|
||||
+ """
|
||||
+ Safely call a given method on a given object of a given service over DBus
|
||||
+ passing given arguments. If a connection is given, it is used, otherwise a
|
||||
+ new connection is established. Safely means that it is a synchronous,
|
||||
+ thread-safe call not using any main loop.
|
||||
+
|
||||
+ :param service: DBus service to use
|
||||
+ :type service: str
|
||||
+ :param obj_path: object path of the object to call method on
|
||||
+ :type obj_path: str
|
||||
+ :param iface: interface to use
|
||||
+ :type iface: str
|
||||
+ :param method: name of the method to call
|
||||
+ :type method: str
|
||||
+ :param args: arguments to pass to the method
|
||||
+ :type args: GVariant
|
||||
+ :param connection: connection to use (if None, a new connection is
|
||||
+ established)
|
||||
+ :type connection: Gio.DBusConnection
|
||||
+ :param fds: list of file descriptors for the call
|
||||
+ :type: Gio.UnixFDList
|
||||
+ :param timeout: timeout in milliseconds for the call (-1 for default timeout)
|
||||
+ :type timeout: int
|
||||
+ :return: unpacked value returned by the method
|
||||
+ :rtype: tuple with elements that depend on the method
|
||||
+ :raise DBusCallError: if some DBus related error appears
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ if not connection:
|
||||
+ try:
|
||||
+ connection = get_new_system_connection()
|
||||
+ except GLib.GError as gerr:
|
||||
+ raise DBusCallError("Unable to connect to system bus: %s" % gerr)
|
||||
+
|
||||
+ if connection.is_closed():
|
||||
+ raise DBusCallError("Connection is closed")
|
||||
+
|
||||
+ try:
|
||||
+ ret = connection.call_with_unix_fd_list_sync(service, obj_path, iface, method, args,
|
||||
+ None, Gio.DBusCallFlags.NONE,
|
||||
+ timeout, fds, None)
|
||||
+ except GLib.GError as gerr:
|
||||
+ msg = "Failed to call %s method on %s with %s arguments: %s" % \
|
||||
+ (method, obj_path, args, gerr.message) # pylint: disable=no-member
|
||||
+ raise DBusCallError(msg)
|
||||
+
|
||||
+ if ret is None:
|
||||
+ msg = "No return from %s method on %s with %s arguments" % (method, obj_path, args)
|
||||
+ raise DBusCallError(msg)
|
||||
+
|
||||
+ return ret[0].unpack()
|
||||
+
|
||||
+
|
||||
+def get_property_sync(service, obj_path, iface, prop_name,
|
||||
+ connection=None):
|
||||
+ """
|
||||
+ Get value of a given property of a given object provided by a given service.
|
||||
+
|
||||
+ :param service: DBus service to use
|
||||
+ :type service: str
|
||||
+ :param obj_path: object path
|
||||
+ :type obj_path: str
|
||||
+ :param iface: interface to use
|
||||
+ :type iface: str
|
||||
+ :param prop_name: name of the property
|
||||
+ :type prop_name: str
|
||||
+ :param connection: connection to use (if None, a new connection is
|
||||
+ established)
|
||||
+ :type connection: Gio.DBusConnection
|
||||
+ :return: unpacked value of the property
|
||||
+ :rtype: tuple with elements that depend on the type of the property
|
||||
+ :raise DBusCallError: when the internal dbus_call_safe_sync invocation
|
||||
+ raises an exception
|
||||
+ :raise DBusPropertyError: when the given object doesn't have the given
|
||||
+ property
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ args = GLib.Variant('(ss)', (iface, prop_name))
|
||||
+ ret = call_sync(service, obj_path, DBUS_PROPS_IFACE, "Get", args,
|
||||
+ connection)
|
||||
+ if ret is None:
|
||||
+ msg = "No value for the %s object's property %s" % (obj_path, prop_name)
|
||||
+ raise DBusPropertyError(msg)
|
||||
+
|
||||
+ return ret
|
||||
+
|
||||
+
|
||||
+def get_properties_sync(service, obj_path, iface, connection=None):
|
||||
+ """
|
||||
+ Get all properties of a given object provided by a given service.
|
||||
+
|
||||
+ :param service: DBus service to use
|
||||
+ :type service: str
|
||||
+ :param obj_path: object path
|
||||
+ :type obj_path: str
|
||||
+ :param iface: interface to use
|
||||
+ :type iface: str
|
||||
+ :param connection: connection to use (if None, a new connection is
|
||||
+ established)
|
||||
+ :type connection: Gio.DBusConnection
|
||||
+ :return: unpacked value of the property
|
||||
+ :rtype: tuple with elements that depend on the type of the property
|
||||
+ :raise DBusCallError: when the internal dbus_call_safe_sync invocation
|
||||
+ raises an exception
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ args = GLib.Variant('(s)', (iface,))
|
||||
+ ret = call_sync(service, obj_path, DBUS_PROPS_IFACE, "GetAll", args,
|
||||
+ connection)
|
||||
+
|
||||
+ return ret
|
||||
+
|
||||
+
|
||||
+def check_object_available(service, obj_path, iface=None):
|
||||
+ intro_data = call_sync(service, obj_path, DBUS_INTRO_IFACE, "Introspect", None)
|
||||
+ node_info = Gio.DBusNodeInfo.new_for_xml(intro_data[0])
|
||||
+ if not iface:
|
||||
+ # just check if any interface is available (there are none for
|
||||
+ # non-existing objects)
|
||||
+ return bool(node_info.interfaces)
|
||||
+ else:
|
||||
+ return any(intface.name == iface for intface in node_info.interfaces)
|
||||
+
|
||||
--
|
||||
2.51.0
|
||||
|
||||
@ -5,7 +5,7 @@ Version: 3.13.0
|
||||
|
||||
#%%global prerelease .b2
|
||||
# prerelease, if defined, should be something like .a1, .b1, .b2.dev1, or .c2
|
||||
Release: 1%{?prerelease}%{?dist}
|
||||
Release: 2%{?prerelease}%{?dist}
|
||||
Epoch: 1
|
||||
License: LGPL-2.1-or-later
|
||||
%global realname blivet
|
||||
@ -17,6 +17,8 @@ Source1: http://github.com/storaged-project/blivet/releases/download/%{realname}
|
||||
Patch0: 0001-remove-btrfs-plugin.patch
|
||||
%endif
|
||||
|
||||
Patch1: 0002-Temporarily-reintroduce-the-safe_dbus-module.patch
|
||||
|
||||
# Versions of required components (done so we make sure the buildrequires
|
||||
# match the requires versions of things).
|
||||
%global partedver 1.8.1
|
||||
@ -113,6 +115,10 @@ make DESTDIR=%{buildroot} install
|
||||
%{python3_sitelib}/*
|
||||
|
||||
%changelog
|
||||
* Wed Oct 29 2025 Vojtech Trefny <vtrefny@redhat.com> - 3.13.0-2
|
||||
- Temporarily reintroduce the safe_dbus module
|
||||
Related: RHEL-115005
|
||||
|
||||
* Wed Oct 08 2025 Vojtech Trefny <vtrefny@redhat.com> - 3.13.0-1
|
||||
- Update to blivet 3.13.0 upstream release
|
||||
Resolves: RHEL-115005
|
||||
|
||||
Loading…
Reference in New Issue
Block a user