mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-27 02:56:31 +00:00
Shutdown using systemd-logind if available (#2416)
The Reboot() and PowerOff() methods of the systemd D-Bus API are not meant to be called directly when logind is in use. Make sure to use the logind APIs if available. Since OS release 5.1 systemd-logind is enabled.
This commit is contained in:
parent
6b32fa31b6
commit
bd173fa333
@ -6,6 +6,7 @@ from ..const import SOCKET_DBUS
|
||||
from ..coresys import CoreSys, CoreSysAttributes
|
||||
from .hostname import Hostname
|
||||
from .interface import DBusInterface
|
||||
from .logind import Logind
|
||||
from .network import NetworkManager
|
||||
from .rauc import Rauc
|
||||
from .systemd import Systemd
|
||||
@ -21,6 +22,7 @@ class DBusManager(CoreSysAttributes):
|
||||
self.coresys: CoreSys = coresys
|
||||
|
||||
self._systemd: Systemd = Systemd()
|
||||
self._logind: Logind = Logind()
|
||||
self._hostname: Hostname = Hostname()
|
||||
self._rauc: Rauc = Rauc()
|
||||
self._network: NetworkManager = NetworkManager()
|
||||
@ -30,6 +32,11 @@ class DBusManager(CoreSysAttributes):
|
||||
"""Return the systemd interface."""
|
||||
return self._systemd
|
||||
|
||||
@property
|
||||
def logind(self) -> Logind:
|
||||
"""Return the logind interface."""
|
||||
return self._logind
|
||||
|
||||
@property
|
||||
def hostname(self) -> Hostname:
|
||||
"""Return the hostname interface."""
|
||||
@ -55,6 +62,7 @@ class DBusManager(CoreSysAttributes):
|
||||
|
||||
dbus_loads: List[DBusInterface] = [
|
||||
self.systemd,
|
||||
self.logind,
|
||||
self.hostname,
|
||||
self.network,
|
||||
self.rauc,
|
||||
|
@ -18,6 +18,7 @@ DBUS_NAME_NM_CONNECTION_ACTIVE_CHANGED = (
|
||||
"org.freedesktop.NetworkManager.Connection.Active.PropertiesChanged"
|
||||
)
|
||||
DBUS_NAME_SYSTEMD = "org.freedesktop.systemd1"
|
||||
DBUS_NAME_LOGIND = "org.freedesktop.login1"
|
||||
|
||||
DBUS_OBJECT_BASE = "/"
|
||||
DBUS_OBJECT_DNS = "/org/freedesktop/NetworkManager/DnsManager"
|
||||
@ -25,6 +26,7 @@ DBUS_OBJECT_SETTINGS = "/org/freedesktop/NetworkManager/Settings"
|
||||
DBUS_OBJECT_HOSTNAME = "/org/freedesktop/hostname1"
|
||||
DBUS_OBJECT_NM = "/org/freedesktop/NetworkManager"
|
||||
DBUS_OBJECT_SYSTEMD = "/org/freedesktop/systemd1"
|
||||
DBUS_OBJECT_LOGIND = "/org/freedesktop/login1"
|
||||
|
||||
DBUS_ATTR_ACTIVE_CONNECTIONS = "ActiveConnections"
|
||||
DBUS_ATTR_ACTIVE_CONNECTION = "ActiveConnection"
|
||||
|
41
supervisor/dbus/logind.py
Normal file
41
supervisor/dbus/logind.py
Normal file
@ -0,0 +1,41 @@
|
||||
"""Interface to Logind over D-Bus."""
|
||||
import logging
|
||||
|
||||
from ..exceptions import DBusError, DBusInterfaceError
|
||||
from ..utils.gdbus import DBus
|
||||
from .const import DBUS_NAME_LOGIND, DBUS_OBJECT_LOGIND
|
||||
from .interface import DBusInterface
|
||||
from .utils import dbus_connected
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Logind(DBusInterface):
|
||||
"""Logind function handler."""
|
||||
|
||||
name = DBUS_NAME_LOGIND
|
||||
|
||||
async def connect(self):
|
||||
"""Connect to D-Bus."""
|
||||
try:
|
||||
self.dbus = await DBus.connect(DBUS_NAME_LOGIND, DBUS_OBJECT_LOGIND)
|
||||
except DBusError:
|
||||
_LOGGER.warning("Can't connect to systemd-logind")
|
||||
except DBusInterfaceError:
|
||||
_LOGGER.info("No systemd-logind support on the host.")
|
||||
|
||||
@dbus_connected
|
||||
def reboot(self):
|
||||
"""Reboot host computer.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
return self.dbus.Manager.Reboot(False)
|
||||
|
||||
@dbus_connected
|
||||
def power_off(self):
|
||||
"""Power off host computer.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
return self.dbus.Manager.PowerOff(False)
|
@ -19,7 +19,9 @@ class SystemControl(CoreSysAttributes):
|
||||
|
||||
def _check_dbus(self, flag):
|
||||
"""Check if systemd is connect or raise error."""
|
||||
if flag == MANAGER and self.sys_dbus.systemd.is_connected:
|
||||
if flag == MANAGER and (
|
||||
self.sys_dbus.systemd.is_connected or self.sys_dbus.logind.is_connected
|
||||
):
|
||||
return
|
||||
if flag == HOSTNAME and self.sys_dbus.hostname.is_connected:
|
||||
return
|
||||
@ -31,20 +33,34 @@ class SystemControl(CoreSysAttributes):
|
||||
"""Reboot host system."""
|
||||
self._check_dbus(MANAGER)
|
||||
|
||||
_LOGGER.info("Initialize host reboot over systemd")
|
||||
use_logind = self.sys_dbus.logind.is_connected
|
||||
_LOGGER.info(
|
||||
"Initialize host reboot using %s", "logind" if use_logind else "systemd"
|
||||
)
|
||||
|
||||
try:
|
||||
await self.sys_core.shutdown()
|
||||
finally:
|
||||
if use_logind:
|
||||
await self.sys_dbus.logind.reboot()
|
||||
else:
|
||||
await self.sys_dbus.systemd.reboot()
|
||||
|
||||
async def shutdown(self):
|
||||
"""Shutdown host system."""
|
||||
self._check_dbus(MANAGER)
|
||||
|
||||
_LOGGER.info("Initialize host power off over systemd")
|
||||
use_logind = self.sys_dbus.logind.is_connected
|
||||
_LOGGER.info(
|
||||
"Initialize host power off %s", "logind" if use_logind else "systemd"
|
||||
)
|
||||
|
||||
try:
|
||||
await self.sys_core.shutdown()
|
||||
finally:
|
||||
if use_logind:
|
||||
await self.sys_dbus.logind.power_off()
|
||||
else:
|
||||
await self.sys_dbus.systemd.power_off()
|
||||
|
||||
async def set_hostname(self, hostname):
|
||||
|
Loading…
x
Reference in New Issue
Block a user