Skip to content

Commit

Permalink
Implement support for running on Wayland through Weston
Browse files Browse the repository at this point in the history
This implements rudimentary support for running Anaconda on Wayland
using the Weston compositor through XWayland. This support also
includes simple auth-less VNC remote access, though authenticated
VNC support requires extra effort since Weston's authenticated
VNC support uses TLS certificates and we do not have a good way
to plumb that through right now (more info in weston-vnc(7)).
  • Loading branch information
Conan-Kudo committed Jan 15, 2024
1 parent a8c654b commit ed4288c
Show file tree
Hide file tree
Showing 11 changed files with 851 additions and 360 deletions.
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
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
1 change: 1 addition & 0 deletions data/systemd/anaconda.service
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ 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
WorkingDirectory=/root
ExecStart=/usr/bin/tmux -u -f /usr/share/anaconda/tmux.conf start
PAMName=anaconda
14 changes: 14 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,24 @@ 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"

# Timeout for starting Wayland
WAYLAND_TIMEOUT = 60

# Timeout for starting X
X_TIMEOUT = 60

Expand Down
66 changes: 65 additions & 1 deletion pyanaconda/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import configparser
import os
import os.path
import subprocess
Expand All @@ -40,7 +41,8 @@
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
IPMI_ABORTED, WAYLAND_SOCKET_NAME, 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 +167,68 @@ 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 config file for Weston
weston_config_file = tempfile.NamedTemporaryFile(suffix="-wl-weston-sysinstall-ini",
delete=False)
weston_config_ini = configparser.ConfigParser()
for section, options in weston_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)

log.debug("Starting Weston.")
argv = ["weston", f"--config={weston_config_file}", "--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")
path = os.path.join(xdg_runtime_dir, WAYLAND_SOCKET_NAME)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
sock.connect(path)
sock.close()
wl_status.started = True
return wl_status.started
except Exception:
if wl_status.needs_waiting():
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

0 comments on commit ed4288c

Please sign in to comment.