Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback to Wayland if Xorg is not available #5309

Closed
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
26 changes: 26 additions & 0 deletions anaconda.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@
# ...still messy (2013-07-12)
# A lot less messy now. :) (2016-10-13)

print("AAA MINIMAL GTK EXAMPLE")

import time
import os
import shlex
import subprocess


print("AAA set ENV early")
# FIXME: check if we need to define these env vars here or not
os.environ["XDG_RUNTIME_DIR"] = "/run/user/0"
os.environ["GDK_BACKEND"] = "wayland"
os.environ["XDG_SESSION_TYPE"] = "wayland"

print("AAA: ENVIRON")
print(os.environ)

import os
import atexit
import sys
Expand Down Expand Up @@ -172,6 +189,13 @@ def setup_environment():
print("anaconda must be run as root.")
sys.exit(1)

# FIXME: try setting XDG_RUNTIME_DIR early
os.environ["XDG_RUNTIME_DIR"] = "/run/user/0"
# FIXME: enable GTK startup debugging
os.environ["G_MESSAGES_DEBUG"] = "all"
os.environ["GDK_DEBUG"] = "all"
# os.environ["GTK_DEBUG"] = "all"

print("Starting installer, one moment...")

# Allow a file to be loaded as early as possible
Expand Down Expand Up @@ -226,6 +250,8 @@ def setup_environment():
if startup_utils.prompt_for_ssh(opts):
sys.exit(0)

log.debug("AAA: MAIN PID/PPID %d/%d", os.getpid(), os.getppid())

log.info("%s %s", sys.argv[0], util.get_anaconda_version_string(build_time_version=True))
# Do not exceed default 8K limit on message length in rsyslog
for log_line in util.get_image_packages_info(max_string_chars=8096-100):
Expand Down
23 changes: 23 additions & 0 deletions anaconda.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ Requires: nm-connection-editor
Requires: librsvg2
Requires: gnome-kiosk
Requires: brltty
# Wayland support dependecies
# FIXME: conditionalize this ?
Requires: python3-pam
Requires: sssd-client
Requires: xorg-x11-server-Xwayland
# dependencies for rpm-ostree payload module
Requires: rpm-ostree >= %{rpmostreever}
Requires: ostree
Expand Down Expand Up @@ -343,13 +348,29 @@ runtime on NFS/HTTP/FTP servers or local disks.
%configure ANACONDA_RELEASE=%{release} %{!?with_glade:--disable-glade}
%{__make} %{?_smp_mflags}

# FIXME: pam profile
cat > anaconda-session <<EOF
#%PAM-1.0
auth sufficient pam_permit.so
account sufficient pam_permit.so
password sufficient pam_permit.so
session required pam_loginuid.so
-session optional pam_keyinit.so revoke
-session optional pam_limits.so
session required pam_systemd.so
EOF

%install
%{make_install}
find %{buildroot} -type f -name "*.la" | xargs %{__rm}

# Create an empty directory for addons
mkdir %{buildroot}%{_datadir}/anaconda/addons

# FIXME: pam profile
mkdir %{buildroot}/etc/pam.d
install -m 755 anaconda-session %{buildroot}/etc/pam.d/anaconda-session

# Create an empty directory for post-scripts
mkdir %{buildroot}%{_datadir}/anaconda/post-scripts

Expand Down Expand Up @@ -389,6 +410,7 @@ rm -rf \
%license COPYING
%{_unitdir}/*
%{_prefix}/lib/systemd/system-generators/*
%{_bindir}/run-in-new-session.py
%{_bindir}/anaconda-disable-nm-ibft-plugin
%{_bindir}/anaconda-nm-disable-autocons
%{_sbindir}/anaconda
Expand All @@ -414,6 +436,7 @@ rm -rf \
%config %{_sysconfdir}/%{name}/conf.d/*
%dir %{_sysconfdir}/%{name}/profile.d
%config %{_sysconfdir}/%{name}/profile.d/*
%config %{_sysconfdir}/pam.d/anaconda-session

%if %{with live}
# do not provide the live subpackage on RHEL
Expand Down
1 change: 1 addition & 0 deletions dockerfile/anaconda-iso-creator/lorax-build
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ createrepo_c $REPO_DIR
# The --volid argument can cause different network interface naming: https://github.com/rhinstaller/kickstart-tests/issues/448
lorax -p Fedora -v "$VERSION_ID" -r "$VERSION_ID" \
--volid Fedora-S-dvd-x86_64-rawh \
--rootfs-size 5 \
-s http://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/ \
-s file://$REPO_DIR/ \
"$@" \
Expand Down
137 changes: 126 additions & 11 deletions pyanaconda/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.process_watchers import WatchProcesses
from pyanaconda.core.kernel import kernel_arguments
from pyanaconda import startup_utils
from pyanaconda.core import util, constants, hw
from pyanaconda import vnc
Expand All @@ -50,6 +51,10 @@
log = get_module_logger(__name__)
stdout_log = get_stdout_logger()

import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk

X_TIMEOUT_ADVICE = \
"Do not load the stage2 image over a slow network link.\n" \
"Wait longer for the X server startup with the inst.xtimeout=<SECONDS> boot option." \
Expand Down Expand Up @@ -245,6 +250,91 @@ def write_xdriver(driver, root=None):
f.close()


# Wayland

def start_wayland_compositor():
"""Start Wayland compositor for the Anaconda GUI.

Add XDG_DATA_DIRS to the environment to pull in our overridden schema
files.

FIXME: Will XDG_DATA_DIRS work with Wayland compositor ?
"""
# mark Wayland is in use
# FIXME: is this the correct place to set this flag ?
flags.wayland = True

datadir = os.environ.get('ANACONDA_DATADIR', '/usr/share/anaconda')
if 'XDG_DATA_DIRS' in os.environ:
xdg_data_dirs = datadir + '/window-manager:' + os.environ['XDG_DATA_DIRS']
else:
xdg_data_dirs = datadir + '/window-manager:/usr/share'

def wayland_preexec():
# to set GUI subprocess SIGINT handler
# FIXME: does this even work with a Wayland compoitor ?
signal.signal(signal.SIGINT, signal.SIG_IGN)

# childproc = util.startProgram(["gnome-kiosk", "--sm-disable", "--wayland"],
# env_add={
# 'XDG_DATA_DIRS': xdg_data_dirs,
# 'XDG_RUNTIME_DIR': "/run/user/0"},
# preexec_fn=wayland_preexec)


#"/run-in-new-session.py --user root --service anaconda-session --session-type wayland --session-class user /bin/gnome-kiosk --wayland --sm-disable"

log.debug("AAA: DISPLAY PID/PPID %d/%d", os.getpid(), os.getppid())

# FIXME: try to force wayland
Gdk.set_allowed_backends("wayland")

childproc = util.startProgram(["run-in-new-session.py", "--user", "root",
"--service", "anaconda-session",
"--vt", "6",
"--session-type", "wayland", "--session-class", "user",
"gnome-kiosk", "--sm-disable"],
env_add={
'XDG_DATA_DIRS': xdg_data_dirs,
'XDG_RUNTIME_DIR': "/run/user/0"},
preexec_fn=wayland_preexec)

#WatchProcesses.watch_process(childproc, "gnome-kiosk")

WatchProcesses.watch_process(childproc, "run-in-new-session.py")

# FIXME: could WatchProcesses do this & what is it for actually ?
# Make sure gnome-kiosk is running, before continuing. Otherwise the GUI
# might try to connect to the Wayland compositor before its ready &
# will fail to to start.
log.debug("waiting for Wayland compositor (gnome-kiosk) to start")
while not os.path.exists('/run/user/0/wayland-0'):
time.sleep(0.1)
log.debug("Wayland compositor (gnome-kiosk) startup finished & ready to use")

def set_wayland_resolution(runres):
"""Set Wayland server screen resolution.

FIXME: implement this using Mutter DBus API
FIXME: keep runres or use horizontal/vertical resolution instead ?

:param str runres: a resolution specification string
"""
log.error("FIXME: set screen resolution - not yet implemented on Wayland")


def do_extra_wayland_actions(runres, gui_mode):
"""Perform Wayland related actions not related to startup.

:param str runres: a resolution specification string
:param gui_mode: an Anaconda display mode
"""
if runres and gui_mode and not flags.usevnc:
set_wayland_resolution(runres)

start_user_systemd()


# general display startup
def setup_display(anaconda, options):
"""Setup the display for the installation environment.
Expand Down Expand Up @@ -320,16 +410,35 @@ def setup_display(anaconda, options):
for error_message in vnc_error_messages:
stdout_log.warning(error_message)

# Should we try to start Xorg?
want_x = anaconda.gui_mode and not (flags.preexisting_x11 or flags.usevnc)

# Is Xorg is actually available?
if want_x and not os.access("/usr/bin/Xorg", os.X_OK):
stdout_log.warning(_("Graphical installation is not available. "
"Starting text mode."))
time.sleep(2)
anaconda.display_mode = constants.DisplayModes.TUI
want_x = False
# Xorg or Wayland?
want_x = False
want_wayland = False

# try to run in local GUI mode
if anaconda.gui_mode and not (flags.preexisting_x11 or flags.usevnc):
# is Xorg actually available?
xorg_server_available = os.access("/usr/bin/Xorg", os.X_OK)

# is our Wayland compositor available ?
wayland_compositor_available = os.access("/usr/bin/gnome-kiosk", os.X_OK)

# do we have at least one of the needed deps we need to run in graphical mode ?
if xorg_server_available:
# check for Wayland override
if "wayland" in kernel_arguments and wayland_compositor_available:
# this way we can test if insaller on Wayland works on a given system
want_wayland = True
else:
# no Wayland override or no Wayland, just use X
want_x = True
elif wayland_compositor_available:
want_wayland = True
else:
# neither X or Wayland is available
anaconda.display_mode = constants.DisplayModes.TUI
stdout_log.warning(_("Graphical installation is not available. "
"Starting text mode."))
time.sleep(2)

if anaconda.tui_mode and flags.vncquestion:
# we prefer vnc over text mode, so ask about that
Expand All @@ -347,7 +456,13 @@ def setup_display(anaconda, options):

# check_memory may have changed the display mode
want_x = want_x and (anaconda.gui_mode)
if want_x:
want_wayland = want_wayland and (anaconda.gui_mode)

if want_wayland:
log.debug("Using Wayland compositor to provide locally running graphical interface.")
start_wayland_compositor()
elif want_x:
log.debug("Using Xorg server to provide locally running graphical interface.")
try:
start_x11(xtimeout)
do_startup_x11_actions()
Expand Down
1 change: 1 addition & 0 deletions pyanaconda/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(self):
self.usevnc = False
self.vncquestion = True
self.preexisting_x11 = False
self.wayland = False
self.automatedInstall = False
self.eject = True
# ksprompt is whether or not to prompt for missing ksdata
Expand Down
2 changes: 2 additions & 0 deletions pyanaconda/ui/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ def __init__(self, fullscreen=False, decorated=False):
:param bool fullscreen: if True, fullscreen the window, if false maximize
"""
super().__init__()

# Keep the latest main window.
self.__class__.__instance = self

Expand Down Expand Up @@ -672,6 +673,7 @@ def _instantiateAction(self, actionClass):
return obj

def run(self):
log.debug("AAA: GTK PID/PPID %d/%d", os.getpid(), os.getppid())
(success, _args) = Gtk.init_check(None)
if not success:
raise RuntimeError("Failed to initialize Gtk")
Expand Down
Loading
Loading