mirror of
https://github.com/facebook/sapling.git
synced 2024-09-11 10:36:52 +03:00
Improve error message if systemd is not running
Summary: If the systemd user manager is not running (e.g. it crashed or was manually stopped), 'eden stop' fails with an unhelpful error message: > pystemd.dbusexc.DBusConnectionRefusedError: [err -111]: Could not open a bus to DBus or > pystemd.dbusexc.DBusBaseError: [err -2]: Could not open a bus to DBus Provide a better experience: tell the user the most likely cause, and suggest a solution: > error: The systemd user manager is not running. Run the following command to start it, then try again: > sudo systemctl start user@strager.service Reviewed By: wez Differential Revision: D13791023 fbshipit-source-id: 5172df0a52d21c311b27b8a527cad934f9882154
This commit is contained in:
parent
6aa6599178
commit
5d8e8a5fcd
@ -9,6 +9,7 @@
|
||||
|
||||
import asyncio
|
||||
import errno
|
||||
import getpass
|
||||
import os
|
||||
import pathlib
|
||||
import signal
|
||||
@ -20,6 +21,8 @@ from .config import EdenInstance
|
||||
from .logfile import forward_log_file
|
||||
from .systemd import (
|
||||
EdenFSSystemdServiceConfig,
|
||||
SystemdConnectionRefusedError,
|
||||
SystemdFileNotFoundError,
|
||||
SystemdServiceFailedToStartError,
|
||||
SystemdUserBus,
|
||||
edenfs_systemd_service_name,
|
||||
@ -274,6 +277,15 @@ def start_systemd_service(
|
||||
start_task = loop.create_task(start_service_async())
|
||||
loop.create_task(log_forwarder.poll_forever_async())
|
||||
return loop.run_until_complete(start_task)
|
||||
except (SystemdConnectionRefusedError, SystemdFileNotFoundError):
|
||||
print_stderr(
|
||||
f"error: The systemd user manager is not running. Run the "
|
||||
f"following command to\n"
|
||||
f"start it, then try again:\n"
|
||||
f"\n"
|
||||
f" sudo systemctl start user@{getpass.getuser()}.service"
|
||||
)
|
||||
return 1
|
||||
except SystemdServiceFailedToStartError as e:
|
||||
print_stderr(f"error: {e}")
|
||||
return 1
|
||||
|
@ -21,6 +21,7 @@ import typing
|
||||
pystemd_import_error = None
|
||||
try:
|
||||
import pystemd
|
||||
import pystemd.dbusexc # pyre-ignore[21]: T32805591
|
||||
import pystemd.dbuslib # pyre-ignore[21]: T32805591
|
||||
import pystemd.systemd1.manager
|
||||
import pystemd.systemd1.unit
|
||||
@ -749,6 +750,18 @@ def escape_dbus_address(input: bytes) -> bytes:
|
||||
return b"".join(result_pieces)
|
||||
|
||||
|
||||
if pystemd_import_error is None:
|
||||
SystemdConnectionRefusedError = (
|
||||
pystemd.dbusexc.DBusConnectionRefusedError # pyre-ignore[16]: T32805591
|
||||
)
|
||||
SystemdFileNotFoundError = (
|
||||
pystemd.dbusexc.DBusFileNotFoundError # pyre-ignore[16]: T32805591
|
||||
)
|
||||
else:
|
||||
SystemdConnectionRefusedError = Exception
|
||||
SystemdFileNotFoundError = Exception
|
||||
|
||||
|
||||
class SystemdServiceFailedToStartError(Exception):
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -8,6 +8,7 @@
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
@ -147,15 +148,38 @@ class SystemdTest(
|
||||
"journalctl doesn't work and should not be mentioned",
|
||||
)
|
||||
|
||||
def test_eden_start_reports_error_if_systemd_is_not_running(self) -> None:
|
||||
def test_eden_start_reports_error_if_systemd_is_dead(self) -> None:
|
||||
self.set_up_edenfs_systemd_service()
|
||||
systemd = self.systemd
|
||||
assert systemd is not None
|
||||
systemd.exit()
|
||||
self.assertTrue(
|
||||
(systemd.xdg_runtime_dir / "systemd" / "private").exists(),
|
||||
"systemd's socket file should still exist",
|
||||
)
|
||||
|
||||
self.spoof_user_name("testuser")
|
||||
start_process = self.spawn_start_with_fake_edenfs()
|
||||
# TODO(strager): Improve this message.
|
||||
start_process.expect_exact("Could not open a bus to DBus")
|
||||
start_process.expect_exact(
|
||||
"error: The systemd user manager is not running. Run the following "
|
||||
"command to\r\nstart it, then try again:"
|
||||
)
|
||||
start_process.expect_exact("sudo systemctl start user@testuser.service")
|
||||
|
||||
def test_eden_start_reports_error_if_systemd_is_dead_and_cleaned_up(self) -> None:
|
||||
self.set_up_edenfs_systemd_service()
|
||||
systemd = self.systemd
|
||||
assert systemd is not None
|
||||
systemd.exit()
|
||||
shutil.rmtree(systemd.xdg_runtime_dir)
|
||||
|
||||
self.spoof_user_name("testuser")
|
||||
start_process = self.spawn_start_with_fake_edenfs()
|
||||
start_process.expect_exact(
|
||||
"error: The systemd user manager is not running. Run the following "
|
||||
"command to\r\nstart it, then try again:"
|
||||
)
|
||||
start_process.expect_exact("sudo systemctl start user@testuser.service")
|
||||
|
||||
def test_eden_start_uses_fallback_if_systemd_environment_is_missing(self) -> None:
|
||||
self.set_up_edenfs_systemd_service()
|
||||
@ -208,3 +232,7 @@ class SystemdTest(
|
||||
config_d.mkdir()
|
||||
with open(config_d / "systemd.toml", "w") as config_file:
|
||||
toml.dump(config, config_file)
|
||||
|
||||
def spoof_user_name(self, user_name: str) -> None:
|
||||
self.set_environment_variable("LOGNAME", user_name)
|
||||
self.set_environment_variable("USER", user_name)
|
||||
|
Loading…
Reference in New Issue
Block a user