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

Implement support for running on Wayland through Weston #5401

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
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
21 changes: 17 additions & 4 deletions anaconda.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,22 @@ def setup_environment():
if "LD_PRELOAD" in os.environ:
del os.environ["LD_PRELOAD"]

# Required for Wayland compositors
if os.path.isdir("/tmp/anaconda-xdgrundir"):
os.environ["XDG_RUNTIME_DIR"] = "/tmp/anaconda-xdgrundir"

# Go ahead and set $WAYLAND_DISPLAY whether we're going to use X or not
if "WAYLAND_DISPLAY" in os.environ:
flags.preexisting_wayland = True
else:
os.environ["WAYLAND_DISPLAY"] = constants.WAYLAND_SOCKET_NAME

# Go ahead and set $DISPLAY whether we're going to use X or not
# only if X11 is being used
from pyanaconda.core.kernel import kernel_arguments
if "DISPLAY" in os.environ:
flags.preexisting_x11 = True
else:
elif "x11" in kernel_arguments and os.path.isfile("/usr/bin/Xorg"):
os.environ["DISPLAY"] = ":%s" % constants.X_DISPLAY_NUMBER

# We mostly don't run from bash, so it won't load the file for us, and libreport will then
Expand Down Expand Up @@ -296,10 +308,11 @@ def setup_environment():
except pid.PidFileError as e:
log.error("Unable to create %s, exiting", pidfile.filename)

# If we had a $DISPLAY at start and zenity is available, we may be
# running in a live environment and we can display an error dialog.
# If we had a Wayland/X11 display at start and zenity is available,
# we may be running in a live environment and we can display an error dialog.
# Otherwise just print an error.
if flags.preexisting_x11 and os.access("/usr/bin/zenity", os.X_OK):
preexisting_graphics = flags.preexisting_wayland or flags.preexisting_x11
if preexisting_graphics and os.access("/usr/bin/zenity", os.X_OK):
# The module-level _() calls are ok here because the language may
# be set from the live environment in this case, and anaconda's
# language setup hasn't happened yet.
Expand Down
8 changes: 7 additions & 1 deletion anaconda.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,20 @@ Requires: zram-generator
# needed for proper driver disk support - if RPMs must be installed, a repo is needed
Requires: createrepo_c
# Display stuff moved from lorax templates
## For Wayland
Requires: weston
Requires: xorg-x11-server-Xwayland
## For X11
Requires: xorg-x11-drivers
Requires: xorg-x11-server-Xorg
Requires: xrandr
Requires: gnome-kiosk
## Common stuff
Requires: xrdb
Requires: dbus-x11
Requires: gsettings-desktop-schemas
Requires: nm-connection-editor
Requires: librsvg2
Requires: gnome-kiosk
Requires: brltty
# dependencies for rpm-ostree payload module
Requires: rpm-ostree >= %{rpmostreever}
Expand Down Expand Up @@ -394,6 +399,7 @@ rm -rf \
%{_sbindir}/anaconda
%{_sbindir}/handle-sshpw
%{_datadir}/anaconda
%{_sysconfdir}/pam.d/anaconda
%{_prefix}/libexec/anaconda
%exclude %{_datadir}/anaconda/gnome
%exclude %{_datadir}/anaconda/pixmaps
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ AC_CONFIG_FILES([Makefile
data/liveinst/gnome/Makefile
data/systemd/Makefile
data/dbus/Makefile
data/pam/Makefile
data/window-manager/Makefile
data/window-manager/config/Makefile
po/Makefile
Expand Down
2 changes: 1 addition & 1 deletion data/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

SUBDIRS = command-stubs liveinst systemd pixmaps window-manager dbus conf.d profile.d
SUBDIRS = command-stubs liveinst systemd pixmaps window-manager dbus conf.d profile.d pam

CLEANFILES = *~

Expand Down
21 changes: 21 additions & 0 deletions data/pam/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (C) 2024 Neal Gompa.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

CLEANFILES = *~

pamdir = $(sysconfdir)/pam.d
dist_pam_DATA = anaconda

MAINTAINERCLEANFILES = Makefile.in
8 changes: 8 additions & 0 deletions data/pam/anaconda
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#%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
11 changes: 10 additions & 1 deletion data/systemd/anaconda.service
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ Wants=anaconda-noshell.service

[Service]
Type=forking
Environment=HOME=/root MALLOC_CHECK_=2 MALLOC_PERTURB_=204 PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin LANG=en_US.UTF-8 GDK_BACKEND=x11 XDG_RUNTIME_DIR=/tmp GIO_USE_VFS=local
Environment=HOME=/root MALLOC_CHECK_=2 MALLOC_PERTURB_=204 PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin LANG=en_US.UTF-8 GDK_BACKEND=x11 XDG_RUNTIME_DIR=/tmp/anaconda-xdgrundir GIO_USE_VFS=local
WorkingDirectory=/root
User=root
Group=root
ExecStartPre=/usr/bin/mkdir -p /tmp/anaconda-xdgrundir
ExecStartPre=/usr/bin/chmod 700 /tmp/anaconda-xdgrundir
ExecStart=/usr/bin/tmux -u -f /usr/share/anaconda/tmux.conf start
PAMName=anaconda
TTYPath=/dev/tty6
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
1 change: 1 addition & 0 deletions dockerfile/anaconda-iso-creator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ RUN set -ex; \
COPY ["lorax-build", "/"]
COPY ["lorax-build-webui", "/"]
COPY ["adjust-templates-for-webui.patch", "/"]
COPY ["adjust-templates-for-weston.patch", "/"]

RUN mkdir /lorax /anaconda-rpms /images

Expand Down
56 changes: 56 additions & 0 deletions dockerfile/anaconda-iso-creator/adjust-templates-for-weston.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
From 3b6fcfc755ee9b2a5b4de7965ee2e3fc41045379 Mon Sep 17 00:00:00 2001
From: Neal Gompa <[email protected]>
Date: Thu, 18 Jan 2024 11:59:00 -0500
Subject: [PATCH] templates.d/99-generic/runtime-cleanup: Do not purge sound
packages

These cause the build to fail when adding Weston to the boot.iso.
---
share/templates.d/99-generic/runtime-cleanup.tmpl | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/share/templates.d/99-generic/runtime-cleanup.tmpl b/share/templates.d/99-generic/runtime-cleanup.tmpl
index aad31f77..e4148b7c 100644
--- a/share/templates.d/99-generic/runtime-cleanup.tmpl
+++ b/share/templates.d/99-generic/runtime-cleanup.tmpl
@@ -9,8 +9,6 @@ remove usr/share/i18n
## perl needed for powerpc-utils
## perl is needed by /usr/bin/rxe_cfg from libibverbs

-## no sound support, thanks
-removepkg flac-libs libsndfile pipewire pulseaudio* rtkit sound-theme-freedesktop wireplumber*
## we don't create new initramfs/bootloader conf inside anaconda
## (that happens inside the target system after we install dracut/grubby)
removepkg dracut-network grubby anaconda-dracut
@@ -52,7 +50,6 @@ removepkg mtools glibc-gconv-extra

## various other things we remove to save space
removepkg diffutils file
-removepkg libasyncns
removepkg lvm2-libs
removepkg mobile-broadband-provider-info
removepkg rmt rpcbind squashfs-tools
@@ -196,7 +193,6 @@ removefrom libidn2 /usr/share/locale/*
removefrom libnotify /usr/bin/*
removefrom libsemanage /etc/selinux/*
removefrom libstdc++ /usr/share/*
-removefrom libvorbis /usr/${libdir}/libvorbisenc.*
removefrom libxml2 /usr/bin/*
removefrom linux-firmware /usr/lib/firmware/dvb*
removefrom linux-firmware /usr/lib/firmware/*_12mhz*
@@ -365,11 +361,7 @@ removefrom gstreamer1-plugins-base --allbut \
removepkg geoclue2

## And remove the packages that those extra libraries pulled in
-removepkg cdparanoia-libs opus libtheora libvisual flac-libs gsm avahi-glib avahi-libs \
- ModemManager-glib
-
-## metacity requires libvorbis and libvorbisfile, but enc/dec are no longer needed
-removefrom libvorbis --allbut /usr/${libdir}/libvorbisfile.* /usr/${libdir}/libvorbis.*
+removepkg cdparanoia-libs libvisual avahi-glib avahi-libs ModemManager-glib

## Remove build-id links, they are used with debuginfo
remove /usr/lib/.build-id
--
2.43.0

4 changes: 4 additions & 0 deletions dockerfile/anaconda-iso-creator/lorax-build
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ mkdir -p $REPO_DIR
cp -a $INPUT_RPMS/* $REPO_DIR || echo "RPM files can't be copied!" # We could just do the build with official repositories only
createrepo_c $REPO_DIR

cp -r /usr/share/lorax/templates.d/ /lorax/
patch -p2 -i /adjust-templates-for-weston.patch

# build boot.iso with our rpms
. /etc/os-release
# The download.fedoraproject.org automatic redirector often selects download-ib01.f.o. for GitHub's cloud, which is too unreliable; use a mirror
# 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 \
--sharedir ./templates.d/99-generic/ \
-s http://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/ \
-s file://$REPO_DIR/ \
"$@" \
Expand Down
4 changes: 4 additions & 0 deletions dockerfile/anaconda-iso-creator/lorax-build.j2
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ mkdir -p $REPO_DIR
cp -a $INPUT_RPMS/* $REPO_DIR || echo "RPM files can't be copied!" # We could just do the build with official repositories only
createrepo_c $REPO_DIR

cp -r /usr/share/lorax/templates.d/ /lorax/
patch -p2 -i /adjust-templates-for-weston.patch

# build boot.iso with our rpms
. /etc/os-release
# The download.fedoraproject.org automatic redirector often selects download-ib01.f.o. for GitHub's cloud, which is too unreliable; use a mirror
Expand All @@ -39,6 +42,7 @@ lorax -p Fedora -v "$VERSION_ID" -r "$VERSION_ID" \
{% else %}
--volid Fedora-S-dvd-x86_64-f{$ distro_release $} \
{% endif %}
--sharedir ./templates.d/99-generic/ \
-s http://dl.fedoraproject.org/pub/fedora/linux/development/{$ distro_release $}/Everything/x86_64/os/ \
-s file://$REPO_DIR/ \
"$@" \
Expand Down
17 changes: 17 additions & 0 deletions pyanaconda/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ class SecretStatus(Enum):
IPMI_ABORTED = 0x9 # installation finished unsuccessfully, due to some non-exn error
IPMI_FAILED = 0xA # installation hit an exception

# Wayland socket name to use
WAYLAND_SOCKET_NAME = "wl-sysinstall-0"

# X display number to use
X_DISPLAY_NUMBER = 1

Expand Down Expand Up @@ -315,13 +318,27 @@ class DisplayModes(Enum):
False: "noninteractive"
}

# Weston configuration
WESTON_CONFIG = {
"core": {
"shell": "kiosk",
"xwayland": "true"
}
}

# Loggers
LOGGER_ANACONDA_ROOT = "anaconda"
LOGGER_MAIN = "anaconda.main"
LOGGER_STDOUT = "anaconda.stdout"
LOGGER_PROGRAM = "program"
LOGGER_SIMPLELINE = "simpleline"

# Wayland display vars file
WAYLAND_DISPLAY_VARS_FILE = "/tmp/anaconda-wayland-display-vars"

# Timeout for starting Wayland
WAYLAND_TIMEOUT = 60

# Timeout for starting X
X_TIMEOUT = 60

Expand Down
95 changes: 93 additions & 2 deletions pyanaconda/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import configparser
import os
import os.path
import pathlib
import subprocess
# Used for ascii_lowercase, ascii_uppercase constants
import tempfile
import time
import re
import signal
import stat
import sys
import types
import inspect
Expand All @@ -39,8 +43,9 @@
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.path import make_directories, open_with_perm, join_paths
from pyanaconda.core.process_watchers import WatchProcesses
from pyanaconda.core.constants import DRACUT_SHUTDOWN_EJECT, \
IPMI_ABORTED, X_TIMEOUT, PACKAGES_LIST_FILE
from pyanaconda.core.constants import DRACUT_SHUTDOWN_EJECT, IPMI_ABORTED, \
WAYLAND_SOCKET_NAME, WAYLAND_DISPLAY_VARS_FILE, WAYLAND_TIMEOUT, \
WESTON_CONFIG, X_TIMEOUT, PACKAGES_LIST_FILE
from pyanaconda.core.live_user import get_live_user
from pyanaconda.errors import RemovedModuleError

Expand Down Expand Up @@ -165,6 +170,92 @@ def preexec():
return partsubp(preexec_fn=preexec)


class WaylandStatus:
"""Status of Wayland launch.

Values of an instance can be modified from the handler functions.
"""
def __init__(self):
self.started = False
self.timed_out = False

def needs_waiting(self):
return not (self.started or self.timed_out)


def startWl(weston_config=WESTON_CONFIG, output_redirect=None, timeout=WAYLAND_TIMEOUT):
""" Start Weston for Wayland and return once Weston is ready to accept connections.

We can identify whether Weston is ready by testing if
the Wayland socket is open yet. Once it is, we can return success.

:param weston_config: The weston.ini(5) configuration to use, as a dictionary
:param output_redirect: file or file descriptor to redirect stdout and stderr to
:param timeout: Number of seconds to timing out.
"""
wl_status = WaylandStatus()

# Create the wayland vars getenv script file for Weston
wl_getenv_script_file = tempfile.NamedTemporaryFile(mode="w",
suffix="-wl-weston-getenv-sh",
delete=False)
wl_getenv_script = f"""#!/bin/sh
rm -f {WAYLAND_DISPLAY_VARS_FILE}
echo "[wayland_vars]" >> {WAYLAND_DISPLAY_VARS_FILE}
echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY" >> {WAYLAND_DISPLAY_VARS_FILE}
echo "DISPLAY=$DISPLAY" >> {WAYLAND_DISPLAY_VARS_FILE}
exit 0
"""
wl_getenv_script_file.write(wl_getenv_script)
wl_getenv_script_file.close()

weston_autolaunch_config = {"autolaunch": {"path": wl_getenv_script_file.name}}

os.chmod(wl_getenv_script_file.name,
os.stat(wl_getenv_script_file.name).st_mode | stat.S_IEXEC)

# Create the config file for Weston
weston_config_file = tempfile.NamedTemporaryFile(mode="w",
suffix="-wl-weston-sysinstall-ini",
delete=False)
weston_config_ini = configparser.ConfigParser()
for section, options in (weston_config | weston_autolaunch_config).items():
weston_config_ini.add_section(section)
for key, value in options.items():
weston_config_ini.set(section, key, str(value))
weston_config_ini.write(weston_config_file, space_around_delimiters=False)
weston_config_file.close()

# Determine whether to use drm or vnc backend
weston_backend = "drm"
if "vnc" in weston_config:
weston_backend = "vnc"

log.debug("Starting Weston.")
argv = ["weston", f"--backend={weston_backend}",
f"--config={weston_config_file.name}", "--log=/tmp/weston.log",
f"--socket={WAYLAND_SOCKET_NAME}"]

childproc = startProgram(argv, stdout=output_redirect, stderr=output_redirect)
WatchProcesses.watch_process(childproc, argv[0])

for _ in range(0, timeout):
try:
xdg_runtime_dir = os.getenv("XDG_RUNTIME_DIR")
pathlib.Path(xdg_runtime_dir, WAYLAND_SOCKET_NAME).resolve(strict=True)
wl_status.started = True
return wl_status.started
except Exception:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be more specific than just Exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, I could, but I have intentionally not done so because I want it to happen in any exception case. It's merely for shorting the loop to iterate on the timeout.

if wl_status.needs_waiting():
time.sleep(1)
wl_status.timed_out = True
WatchProcesses.unwatch_process(childproc)
childproc.terminate()
log.debug("Exception handler test suspended to prevent accidental activation by "
"delayed Weston start.")
raise TimeoutError("Timeout trying to start %s" % argv[0])


class X11Status:
"""Status of Xorg launch.

Expand Down
Loading
Loading