[PATCH 3/3] Inhibit the screen saver on live installs (#928825)
David Shea
dshea at redhat.com
Wed Mar 19 18:04:55 UTC 2014
---
anaconda | 15 ++++++++
data/liveinst/console.apps/liveinst | 4 +-
pyanaconda/anaconda.py | 4 ++
pyanaconda/safe_dbus.py | 44 ++++++++++++++++++++++
pyanaconda/screensaver.py | 73 +++++++++++++++++++++++++++++++++++++
5 files changed, 139 insertions(+), 1 deletion(-)
create mode 100644 pyanaconda/screensaver.py
diff --git a/anaconda b/anaconda
index 4f600eb..3d01944 100755
--- a/anaconda
+++ b/anaconda
@@ -78,6 +78,11 @@ def exitHandler(rebootData, storage, exitCode=None):
loop.controllable = True
dev.deactivate(recursive=True)
+ if anaconda.dbus_inhibit_id:
+ from pyanaconda.screensaver import uninhibit_screensaver
+ uninhibit_screensaver(anaconda.dbus_session_connection, anaconda.dbus_inhibit_id)
+ anaconda.dbus_inhibit_id = None
+
if not flags.imageInstall and not flags.livecdInstall \
and not flags.dirInstall:
from pykickstart.constants import KS_SHUTDOWN, KS_WAIT
@@ -861,8 +866,18 @@ if __name__ == "__main__":
flags.noverifyssl = True
if opts.liveinst:
+ from pyanaconda.safe_dbus import dbus_get_session_connection, DBusCallError
+ from pyanaconda.screensaver import inhibit_screensaver
+
flags.livecdInstall = True
+ try:
+ anaconda.dbus_session_connection = dbus_get_session_connection()
+ except DBusCallError as e:
+ log.info("Unable to connect to DBus session bus: %s", e)
+ else:
+ anaconda.dbus_inhibit_id = inhibit_screensaver(anaconda.dbus_session_connection)
+
if opts.module:
for mod in opts.module:
anaconda.extraModules.append(mod.split(":"))
diff --git a/data/liveinst/console.apps/liveinst b/data/liveinst/console.apps/liveinst
index 7c31081..900ac59 100644
--- a/data/liveinst/console.apps/liveinst
+++ b/data/liveinst/console.apps/liveinst
@@ -3,4 +3,6 @@ PROGRAM=/usr/sbin/liveinst
SESSION=true
# has to be here otherwise consolehelper switches off the waiting cursor too early
STARTUP_NOTIFICATION_NAME="Starting Install to Hard Drive"
-DOMAIN=anaconda
\ No newline at end of file
+DOMAIN=anaconda
+# DBus session connections fail when running setuid unless we pass this through
+KEEP_ENV_VARS=DBUS_SESSION_BUS_ADDRESS
diff --git a/pyanaconda/anaconda.py b/pyanaconda/anaconda.py
index cd12d79..66706f1 100644
--- a/pyanaconda/anaconda.py
+++ b/pyanaconda/anaconda.py
@@ -76,6 +76,10 @@ class Anaconda(object):
# *sigh* we still need to be able to write this out
self.xdriver = None
+ # Data for inhibiting the screensaver
+ self.dbus_session_connection = None
+ self.dbus_inhibit_id = None
+
@property
def bootloader(self):
if not self._bootloader:
diff --git a/pyanaconda/safe_dbus.py b/pyanaconda/safe_dbus.py
index 22a7a04..e9ddfbb 100644
--- a/pyanaconda/safe_dbus.py
+++ b/pyanaconda/safe_dbus.py
@@ -20,12 +20,15 @@
"""Module providing thread-safe and mainloop-safe DBus operations."""
+import os
from gi.repository import GLib, Gio
from pyanaconda.constants import DEFAULT_DBUS_TIMEOUT
DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
DBUS_SYSTEM_BUS_ADDR = Gio.dbus_address_get_for_bus_sync(Gio.BusType.SYSTEM,
None)
+DBUS_SESSION_BUS_ADDR = Gio.dbus_address_get_for_bus_sync(Gio.BusType.SESSION,
+ None)
class SafeDBusError(Exception):
"""Class for exceptions defined in this module."""
@@ -131,3 +134,44 @@ def dbus_get_property_safe_sync(service, obj_path, iface, prop_name,
raise DBusPropertyError(msg)
return ret
+
+def dbus_get_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(
+ DBUS_SESSION_BUS_ADDR,
+ 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
diff --git a/pyanaconda/screensaver.py b/pyanaconda/screensaver.py
new file mode 100644
index 0000000..ce62e5a
--- /dev/null
+++ b/pyanaconda/screensaver.py
@@ -0,0 +1,73 @@
+#
+# screensaver.py - Screensaver management methods and data
+#
+# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): David Shea <dshea at redhat.com>
+#
+
+from pyanaconda.safe_dbus import dbus_call_safe_sync, DBusCallError
+from gi.repository import GLib
+
+import logging
+log = logging.getLogger("anaconda")
+
+SCREENSAVER_SERVICE = "org.freedesktop.ScreenSaver"
+SCREENSAVER_PATH = "/org/freedesktop/ScreenSaver"
+SCREENSAVER_IFACE = "org.freedesktop.ScreenSaver"
+
+SCREENSAVER_INHIBIT_METHOD = "Inhibit"
+SCREENSAVER_UNINHIBIT_METHOD = "UnInhibit"
+
+SCREENSAVER_APPLICATION = "anaconda"
+SCREENSAVER_REASON = "Installing"
+
+def inhibit_screensaver(connection):
+ """
+ Inhibit the screensaver idle timer.
+
+ :param connection: A handle for the session message bus
+ :type connection: Gio.DBusConnection
+ :return: The inhibit ID or None
+ :rtype: int or None
+ """
+
+ try:
+ inhibit_id = dbus_call_safe_sync(SCREENSAVER_SERVICE, SCREENSAVER_PATH, SCREENSAVER_IFACE,
+ SCREENSAVER_INHIBIT_METHOD, GLib.Variant('(ss)',
+ (SCREENSAVER_APPLICATION, SCREENSAVER_REASON)),
+ connection)
+ return inhibit_id[0]
+ except DBusCallError as e:
+ log.info("Unable to inhibit the screensaver: %s", e)
+
+ return None
+
+def uninhibit_screensaver(connection, inhibit_id):
+ """
+ Re-enable the screensaver idle timer.
+
+ :param connection: A handle for the session message bus
+ :type connection: Gio.DBusConnection
+ :param inhibit_id: The ID returned by the inhibit method
+ :type inhibit_id: int
+ """
+
+ try:
+ dbus_call_safe_sync(SCREENSAVER_SERVICE, SCREENSAVER_PATH, SCREENSAVER_IFACE,
+ SCREENSAVER_UNINHIBIT_METHOD, GLib.Variant('(u)', (inhibit_id,)), connection)
+ except DBusCallError as e:
+ log.info("Unable to uninhibit the screensaver: %s", e)
--
1.8.5.3
More information about the anaconda-patches
mailing list