mirror of
https://github.com/facebook/sapling.git
synced 2024-10-08 07:49:11 +03:00
b1a35b8252
Summary: Move the `start_systemd_service()` function from `daemon.py` to a separate module. This allows `daemon.py` to be imported on Windows without causing any of the systemd logic to be imported. I kept this separate from the existing `systemd.py` module for now just to help keep the dependencies a little bit cleaner. The `systemd.py` module currently does not depend on any other logic from other edenfsctl modules. Reviewed By: pkaush Differential Revision: D20854612 fbshipit-source-id: dbdbf0fec90682e3b7d16a7532aefdd3f186bf80
103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2.
|
|
|
|
# pyre-strict
|
|
|
|
import asyncio
|
|
import getpass
|
|
import os
|
|
import pathlib
|
|
import sys
|
|
from typing import List, Optional
|
|
|
|
from . import daemon_util
|
|
from .config import EdenInstance
|
|
from .logfile import forward_log_file
|
|
from .systemd import (
|
|
EdenFSSystemdServiceConfig,
|
|
SystemdConnectionRefusedError,
|
|
SystemdFileNotFoundError,
|
|
SystemdServiceFailedToStartError,
|
|
SystemdUserBus,
|
|
edenfs_systemd_service_name,
|
|
print_service_status_using_systemctl_for_diagnostics_async,
|
|
)
|
|
from .util import print_stderr
|
|
|
|
|
|
def start_systemd_service(
|
|
instance: EdenInstance,
|
|
daemon_binary: Optional[str] = None,
|
|
edenfs_args: Optional[List[str]] = None,
|
|
) -> int:
|
|
try:
|
|
daemon_binary = daemon_util.find_daemon_binary(daemon_binary)
|
|
except daemon_util.DaemonBinaryNotFound as e:
|
|
print_stderr(f"error: {e}")
|
|
return 1
|
|
|
|
service_config = EdenFSSystemdServiceConfig(
|
|
eden_dir=instance.state_dir,
|
|
edenfs_executable_path=pathlib.Path(daemon_binary),
|
|
extra_edenfs_arguments=edenfs_args or [],
|
|
)
|
|
service_config.write_config_file()
|
|
service_name: str = edenfs_systemd_service_name(instance.state_dir)
|
|
xdg_runtime_dir: str = _get_systemd_xdg_runtime_dir(config=instance)
|
|
|
|
startup_log_path = service_config.startup_log_file_path
|
|
startup_log_path.write_bytes(b"")
|
|
with forward_log_file(startup_log_path, sys.stderr.buffer) as log_forwarder:
|
|
loop: asyncio.AbstractEventLoop = asyncio.get_event_loop()
|
|
|
|
async def start_service_async() -> int:
|
|
with SystemdUserBus(
|
|
event_loop=loop, xdg_runtime_dir=xdg_runtime_dir
|
|
) as systemd:
|
|
service_name_bytes = service_name.encode()
|
|
active_state = await systemd.get_unit_active_state_async(
|
|
service_name_bytes
|
|
)
|
|
if active_state == b"active":
|
|
print_stderr("error: edenfs systemd service is already running")
|
|
await print_service_status_using_systemctl_for_diagnostics_async(
|
|
service_name=service_name, xdg_runtime_dir=xdg_runtime_dir
|
|
)
|
|
return 1
|
|
|
|
await systemd.start_service_and_wait_async(service_name_bytes)
|
|
return 0
|
|
|
|
try:
|
|
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
|
|
finally:
|
|
log_forwarder.poll()
|
|
|
|
|
|
def _get_systemd_xdg_runtime_dir(config: EdenInstance) -> str:
|
|
xdg_runtime_dir = os.getenv("XDG_RUNTIME_DIR")
|
|
if xdg_runtime_dir is None:
|
|
xdg_runtime_dir = config.get_fallback_systemd_xdg_runtime_dir()
|
|
print_stderr(
|
|
f"warning: The XDG_RUNTIME_DIR environment variable is not set; "
|
|
f"using fallback: {xdg_runtime_dir!r}"
|
|
)
|
|
return xdg_runtime_dir
|