Skip to content

Commit

Permalink
fix: use login1 dbus API, fix systemd-run (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
gerblesh authored Oct 27, 2024
2 parents c420a9f + 7510d3e commit e18ec42
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 66 deletions.
20 changes: 12 additions & 8 deletions src/ublue_update/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ublue_update.update_inhibitors.hardware import check_hardware_inhibitors
from ublue_update.update_inhibitors.custom import check_custom_inhibitors
from ublue_update.config import cfg
from ublue_update.session import get_active_sessions
from ublue_update.session import get_active_users
from ublue_update.filelock import acquire_lock, release_lock


Expand All @@ -33,16 +33,17 @@ def notify(title: str, body: str, actions: list = [], urgency: str = "normal"):
if process_uid == 0:
users = []
try:
users = get_active_sessions()
users = get_active_users()
except KeyError as e:
log.error("failed to get active logind session info", e)
for user in users:
user_args = [
"/usr/bin/systemd-run",
"--user",
"--machine",
f"{user['user']}@",
"--wait",
f"{user[1]}@", # magic number, corresponds to user name in ListUsers (see session.py)
"--pipe",
"--quiet",
]
user_args += args
out = subprocess.run(user_args, capture_output=True)
Expand Down Expand Up @@ -106,7 +107,7 @@ def run_updates(system, system_update_available):
)
users = []
try:
users = get_active_sessions()
users = get_active_users()
except KeyError as e:
log.error("failed to get active logind session info", e)

Expand All @@ -133,15 +134,18 @@ def run_updates(system, system_update_available):

"""Users"""
for user in users:
log.info(f"""Running update for user: '{user['user']}'""")
log.info(
f"""Running update for user: '{user[1]}'"""
) # magic number, corresponds to username (see session.py)
out = subprocess.run(
[
"/usr/bin/systemd-run",
"--setenv=TOPGRADE_SKIP_BRKC_NOTIFY=true",
"--user",
"--machine",
f"{user['user']}@",
"--wait",
f"{user[1]}@",
"--pipe",
"--quiet",
"/usr/bin/topgrade",
"--config",
"/usr/share/ublue-update/topgrade-user.toml",
Expand Down
24 changes: 16 additions & 8 deletions src/ublue_update/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
import json


def get_active_sessions():
def get_active_users():
out = subprocess.run(
["/usr/bin/loginctl", "list-sessions", "--output=json"],
[
"/usr/bin/busctl",
"--system",
"-j",
"call",
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ListUsers",
],
capture_output=True,
)
sessions = json.loads(out.stdout.decode("utf-8"))
active_sessions = []
for session in sessions:
if session.get("state") == "active":
active_sessions.append(session)
return active_sessions
# https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html
# ListUsers() returns an array of all currently logged in users. The structures in the array consist of the following fields: user id, user name, user object path.
users = json.loads(out.stdout.decode("utf-8"))
# sample output: {'type': 'a(uso)', 'data': [[[1000, 'user', '/org/freedesktop/login1/user/_1000']]]
return users["data"][0]
7 changes: 3 additions & 4 deletions tests/unit/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ def test_notify_uid_user(mock_run, mock_log, mock_os, mock_cfg):
capture_output=True,
)


@patch("ublue_update.cli.cfg")
def test_ask_for_updates_no_dbus_notify(mock_cfg):
mock_cfg.dbus_notify = False
Expand Down Expand Up @@ -163,7 +162,7 @@ def test_run_updates_user_no_system(


@patch("ublue_update.cli.os")
@patch("ublue_update.cli.get_active_sessions")
@patch("ublue_update.cli.get_active_users")
@patch("ublue_update.cli.acquire_lock")
@patch("ublue_update.cli.transaction_wait")
@patch("ublue_update.cli.subprocess.run")
Expand Down Expand Up @@ -212,7 +211,7 @@ def test_run_updates_system(


@patch("ublue_update.cli.os")
@patch("ublue_update.cli.get_active_sessions")
@patch("ublue_update.cli.get_active_users")
@patch("ublue_update.cli.acquire_lock")
@patch("ublue_update.cli.transaction_wait")
@patch("ublue_update.cli.subprocess.run")
Expand Down Expand Up @@ -255,7 +254,7 @@ def test_run_updates_without_image_update(


@patch("ublue_update.cli.os")
@patch("ublue_update.cli.get_active_sessions")
@patch("ublue_update.cli.get_active_users")
@patch("ublue_update.cli.acquire_lock")
@patch("ublue_update.cli.transaction_wait")
@patch("ublue_update.cli.subprocess.run")
Expand Down
66 changes: 21 additions & 45 deletions tests/unit/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,33 @@
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../src"))
)

from ublue_update.session import get_active_sessions
from ublue_update.session import get_active_users

loginctl_json_output = b"""
[
{
"session" : "3",
"uid" : 1001,
"user" : "test",
"seat" : null,
"leader" : 6205,
"class" : "manager",
"tty" : null,
"state": "active",
"idle" : false,
"since" : null
},
{
"session" : "c1",
"uid" : 1001,
"user" : "test",
"seat" : null,
"leader" : 6230,
"class" : "manager",
"tty" : null,
"state": "inactive",
"idle" : false,
"since" : null
}
]
"""
busctl_json_output = b"""{"type":"a(uso)","data":[[[1000,"user","/org/freedesktop/login1/user/_1000"]]]}"""


@patch("ublue_update.session.subprocess.run")
def test_get_active_sessions(mock_run):
def test_get_active_users(mock_run):
mock_run.side_effect = [
MagicMock(stdout=loginctl_json_output),
MagicMock(stdout=busctl_json_output),
]
assert get_active_sessions() == [
{
"session": "3",
"uid": 1001,
"user": "test",
"seat": None,
"leader": 6205,
"class": "manager",
"tty": None,
"state": "active",
"idle": False,
"since": None,
}
assert get_active_users() == [
[
1000,
"user",
"/org/freedesktop/login1/user/_1000",
]
]
mock_run.assert_any_call(
["/usr/bin/loginctl", "list-sessions", "--output=json"], capture_output=True
[
"/usr/bin/busctl",
"--system",
"-j",
"call",
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ListUsers",
],
capture_output=True,
)
2 changes: 1 addition & 1 deletion ublue-update.spec
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ BuildRequires: python-setuptools_scm
BuildRequires: python-wheel
Requires: skopeo
Requires: libnotify
Requires: sudo
Requires: systemd

%global sub_name %{lua:t=string.gsub(rpm.expand("%{NAME}"), "^ublue%-", ""); print(t)}

Expand Down

0 comments on commit e18ec42

Please sign in to comment.