Time handling (#2901)

* Add new time handling

* migrate date for python3.9

* add timedate

* add tests & simplify it

* better testing

* use ssl

* use hostname with new interface

* expose to API

* update data

* add base handler

* new timezone handling

* improve handling

* Improve handling

* Add tests

* Time adjustment function

* Fix logging

* tweak condition

* don't adjust synchronized time

* Guard

* ignore UTC

* small cleanup

* like that, we can leaf it

* add URL

* add comment

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
This commit is contained in:
Pascal Vizeli 2021-06-09 09:38:32 +02:00 committed by GitHub
parent 2f18c177ae
commit bcef34012d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1810 additions and 113 deletions

View File

@ -5,6 +5,7 @@ attrs==21.2.0
awesomeversion==21.5.0
brotli==1.0.9
cchardet==2.1.7
ciso8601==2.1.3
colorlog==5.0.1
cpe==1.2.1
cryptography==3.4.6
@ -13,7 +14,6 @@ docker==5.0.0
gitpython==3.1.17
jinja2==3.0.1
pulsectl==21.5.17
pytz==2021.1
pyudev==0.22.0
ruamel.yaml==0.15.100
sentry-sdk==1.1.0

6
supervisor/api/const.py Normal file
View File

@ -0,0 +1,6 @@
"""Const for API."""
ATTR_USE_RTC = "use_rtc"
ATTR_USE_NTP = "use_ntp"
ATTR_DT_UTC = "dt_utc"
ATTR_DT_SYNCHRONIZED = "dt_synchronized"

View File

@ -21,9 +21,11 @@ from ..const import (
ATTR_OPERATING_SYSTEM,
ATTR_SERVICES,
ATTR_STATE,
ATTR_TIMEZONE,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from .const import ATTR_DT_SYNCHRONIZED, ATTR_DT_UTC, ATTR_USE_NTP, ATTR_USE_RTC
from .utils import api_process, api_process_raw, api_validate
SERVICE = "service"
@ -49,6 +51,11 @@ class APIHost(CoreSysAttributes):
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_KERNEL: self.sys_host.info.kernel,
ATTR_OPERATING_SYSTEM: self.sys_host.info.operating_system,
ATTR_TIMEZONE: self.sys_host.info.timezone,
ATTR_DT_UTC: self.sys_host.info.dt_utc,
ATTR_DT_SYNCHRONIZED: self.sys_host.info.dt_synchronized,
ATTR_USE_NTP: self.sys_host.info.use_ntp,
ATTR_USE_RTC: self.sys_host.info.use_rtc,
}
@api_process

View File

@ -48,5 +48,5 @@ class APIInfo(CoreSysAttributes):
ATTR_SUPPORTED: self.sys_core.supported,
ATTR_CHANNEL: self.sys_updater.channel,
ATTR_LOGGING: self.sys_config.logging,
ATTR_TIMEZONE: self.sys_config.timezone,
ATTR_TIMEZONE: self.sys_timezone,
}

View File

@ -51,7 +51,6 @@ from .snapshots import SnapshotManager
from .store import StoreManager
from .supervisor import Supervisor
from .updater import Updater
from .utils.dt import fetch_timezone
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -95,10 +94,6 @@ async def initialize_coresys() -> CoreSys:
if MACHINE_ID.exists():
coresys.machine_id = MACHINE_ID.read_text().strip()
# Init TimeZone
if coresys.config.timezone == "UTC":
coresys.config.timezone = await fetch_timezone(coresys.websession)
# Set machine type
if os.environ.get(ENV_SUPERVISOR_MACHINE):
coresys.machine = os.environ[ENV_SUPERVISOR_MACHINE]

View File

@ -48,6 +48,11 @@ MEDIA_DATA = PurePath("media")
DEFAULT_BOOT_TIME = datetime.utcfromtimestamp(0).isoformat()
# We filter out UTC because it's the system default fallback
# Core also not respect the cotnainer timezone and reset timezones
# to UTC if the user overflight the onboarding.
_UTC = "UTC"
class CoreConfig(FileConfiguration):
"""Hold all core config data."""
@ -57,13 +62,19 @@ class CoreConfig(FileConfiguration):
super().__init__(FILE_HASSIO_CONFIG, SCHEMA_SUPERVISOR_CONFIG)
@property
def timezone(self) -> str:
def timezone(self) -> Optional[str]:
"""Return system timezone."""
return self._data[ATTR_TIMEZONE]
timezone = self._data.get(ATTR_TIMEZONE)
if timezone != _UTC:
return timezone
self._data.pop(ATTR_TIMEZONE, None)
return None
@timezone.setter
def timezone(self, value: str) -> None:
"""Set system timezone."""
if value == _UTC:
return
self._data[ATTR_TIMEZONE] = value
@property

View File

@ -443,3 +443,4 @@ class HostFeature(str, Enum):
REBOOT = "reboot"
SERVICES = "services"
SHUTDOWN = "shutdown"
TIMEDATE = "timedate"

View File

@ -1,6 +1,7 @@
"""Main file for Supervisor."""
import asyncio
from contextlib import suppress
from datetime import timedelta
import logging
from typing import Awaitable, List, Optional
@ -13,9 +14,13 @@ from .exceptions import (
HomeAssistantCrashError,
HomeAssistantError,
SupervisorUpdateError,
WhoamiError,
WhoamiSSLError,
)
from .homeassistant.core import LANDINGPAGE
from .resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason
from .utils.dt import utcnow
from .utils.whoami import retrieve_whoami
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -109,6 +114,8 @@ class Core(CoreSysAttributes):
self.sys_dbus.load(),
# Load Host
self.sys_host.load(),
# Adjust timezone / time settings
self._adjust_system_datetime(),
# Load Plugins container
self.sys_plugins.load(),
# load last available data
@ -310,6 +317,48 @@ class Core(CoreSysAttributes):
self.sys_config.last_boot = self.sys_hardware.helper.last_boot
self.sys_config.save_data()
async def _adjust_system_datetime(self):
"""Adjust system time/date on startup."""
# If no timezone is detect or set
# If we are not connected or time sync
if (
self.sys_config.timezone
or self.sys_host.info.timezone not in ("Etc/UTC", None)
) and (self.sys_host.info.dt_synchronized or self.sys_supervisor.connectivity):
return
# Get Timezone data
try:
data = await retrieve_whoami(self.sys_websession)
except WhoamiSSLError:
pass
except WhoamiError as err:
_LOGGER.warning("Can't adjust Time/Date settings: %s", err)
return
else:
if not self.sys_config.timezone:
self.sys_config.timezone = data.timezone
return
# Adjust timesettings in case SSL fails
try:
data = await retrieve_whoami(self.sys_websession, with_ssl=False)
except WhoamiError as err:
_LOGGER.error("Can't adjust Time/Date settings: %s", err)
return
else:
if not self.sys_config.timezone:
self.sys_config.timezone = data.timezone
# Calculate if system time is out of sync
delta = data.dt_utc - utcnow()
if delta < timedelta(days=7) or self.sys_host.info.dt_synchronized:
return
_LOGGER.warning("System time/date shift over more as 7days found!")
await self.sys_host.control.set_datetime(data.dt_utc)
await self.sys_supervisor.check_connectivity()
async def repair(self):
"""Repair system integrity."""
_LOGGER.info("Starting repair of Supervisor Environment")

View File

@ -91,6 +91,15 @@ class CoreSys:
"""Return True if we run dev mode."""
return bool(os.environ.get(ENV_SUPERVISOR_DEV, 0))
@property
def timezone(self) -> str:
"""Return system timezone."""
if self.config.timezone:
return self.config.timezone
if self.host.info.timezone:
return self.host.info.timezone
return "UTC"
@property
def loop(self) -> asyncio.BaseEventLoop:
"""Return loop object."""
@ -463,6 +472,11 @@ class CoreSysAttributes:
coresys: CoreSys
@property
def sys_timezone(self) -> str:
"""Return system internal used timezone."""
return self.coresys.timezone
@property
def sys_machine(self) -> Optional[str]:
"""Return running machine type of the Supervisor system."""

View File

@ -10,6 +10,7 @@ from .logind import Logind
from .network import NetworkManager
from .rauc import Rauc
from .systemd import Systemd
from .timedate import TimeDate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -26,6 +27,7 @@ class DBusManager(CoreSysAttributes):
self._hostname: Hostname = Hostname()
self._rauc: Rauc = Rauc()
self._network: NetworkManager = NetworkManager()
self._timedate: TimeDate = TimeDate()
@property
def systemd(self) -> Systemd:
@ -37,6 +39,11 @@ class DBusManager(CoreSysAttributes):
"""Return the logind interface."""
return self._logind
@property
def timedate(self) -> TimeDate:
"""Return the timedate interface."""
return self._timedate
@property
def hostname(self) -> Hostname:
"""Return the hostname interface."""
@ -64,6 +71,7 @@ class DBusManager(CoreSysAttributes):
self.systemd,
self.logind,
self.hostname,
self.timedate,
self.network,
self.rauc,
]

View File

@ -19,6 +19,7 @@ DBUS_NAME_NM_CONNECTION_ACTIVE_CHANGED = (
)
DBUS_NAME_SYSTEMD = "org.freedesktop.systemd1"
DBUS_NAME_LOGIND = "org.freedesktop.login1"
DBUS_NAME_TIMEDATE = "org.freedesktop.timedate1"
DBUS_OBJECT_BASE = "/"
DBUS_OBJECT_DNS = "/org/freedesktop/NetworkManager/DnsManager"
@ -27,6 +28,7 @@ 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_OBJECT_TIMEDATE = "/org/freedesktop/timedate1"
DBUS_ATTR_ACTIVE_CONNECTIONS = "ActiveConnections"
DBUS_ATTR_ACTIVE_CONNECTION = "ActiveConnection"
@ -70,6 +72,11 @@ DBUS_ATTR_VARIANT = "Variant"
DBUS_ATTR_VERSION = "Version"
DBUS_ATTR_MANAGED = "Managed"
DBUS_ATTR_CONNECTION_ENABLED = "ConnectivityCheckEnabled"
DBUS_ATTR_TIMEZONE = "Timezone"
DBUS_ATTR_LOCALRTC = "LocalRTC"
DBUS_ATTR_NTP = "NTP"
DBUS_ATTR_NTPSYNCHRONIZED = "NTPSynchronized"
DBUS_ATTR_TIMEUSEC = "TimeUSec"
class RaucState(str, Enum):

View File

@ -1,6 +1,6 @@
"""D-Bus interface for hostname."""
import logging
from typing import Optional
from typing import Any, Dict, Optional
from ..exceptions import DBusError, DBusInterfaceError
from ..utils.gdbus import DBus
@ -14,7 +14,7 @@ from .const import (
DBUS_NAME_HOSTNAME,
DBUS_OBJECT_HOSTNAME,
)
from .interface import DBusInterface
from .interface import DBusInterface, dbus_property
from .utils import dbus_connected
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -27,56 +27,57 @@ class Hostname(DBusInterface):
def __init__(self):
"""Initialize Properties."""
self._hostname: Optional[str] = None
self._chassis: Optional[str] = None
self._deployment: Optional[str] = None
self._kernel: Optional[str] = None
self._operating_system: Optional[str] = None
self._cpe: Optional[str] = None
self.properties: Dict[str, Any] = {}
async def connect(self):
"""Connect to system's D-Bus."""
try:
self.dbus = await DBus.connect(DBUS_NAME_HOSTNAME, DBUS_OBJECT_HOSTNAME)
except DBusError:
_LOGGER.warning("Can't connect to hostname")
_LOGGER.warning("Can't connect to systemd-hostname")
except DBusInterfaceError:
_LOGGER.warning(
"No hostname support on the host. Hostname functions have been disabled."
)
@property
@dbus_property
def hostname(self) -> Optional[str]:
"""Return local hostname."""
return self._hostname
return self.properties[DBUS_ATTR_STATIC_HOSTNAME]
@property
@dbus_property
def chassis(self) -> Optional[str]:
"""Return local chassis type."""
return self._chassis
return self.properties[DBUS_ATTR_CHASSIS]
@property
@dbus_property
def deployment(self) -> Optional[str]:
"""Return local deployment type."""
return self._deployment
return self.properties[DBUS_ATTR_DEPLOYMENT]
@property
@dbus_property
def kernel(self) -> Optional[str]:
"""Return local kernel version."""
return self._kernel
return self.properties[DBUS_ATTR_KERNEL_RELEASE]
@property
@dbus_property
def operating_system(self) -> Optional[str]:
"""Return local operating system."""
return self._operating_system
return self.properties[DBUS_ATTR_OPERATING_SYSTEM_PRETTY_NAME]
@property
@dbus_property
def cpe(self) -> Optional[str]:
"""Return local CPE."""
return self._cpe
return self.properties[DBUS_ATTR_STATIC_OPERATING_SYSTEM_CPE_NAME]
@dbus_connected
def set_static_hostname(self, hostname):
def set_static_hostname(self, hostname: str):
"""Change local hostname.
Return a coroutine.
@ -86,14 +87,4 @@ class Hostname(DBusInterface):
@dbus_connected
async def update(self):
"""Update Properties."""
data = await self.dbus.get_properties(DBUS_NAME_HOSTNAME)
if not data:
_LOGGER.warning("Can't get properties for Hostname")
return
self._hostname = data.get(DBUS_ATTR_STATIC_HOSTNAME)
self._chassis = data.get(DBUS_ATTR_CHASSIS)
self._deployment = data.get(DBUS_ATTR_DEPLOYMENT)
self._kernel = data.get(DBUS_ATTR_KERNEL_RELEASE)
self._operating_system = data.get(DBUS_ATTR_OPERATING_SYSTEM_PRETTY_NAME)
self._cpe = data.get(DBUS_ATTR_STATIC_OPERATING_SYSTEM_CPE_NAME)
self.properties = await self.dbus.get_properties(DBUS_NAME_HOSTNAME)

View File

@ -1,10 +1,24 @@
"""Interface class for D-Bus wrappers."""
from abc import ABC, abstractmethod
from functools import wraps
from typing import Any, Dict, Optional
from ..utils.gdbus import DBus
def dbus_property(func):
"""Wrap not loaded properties."""
@wraps(func)
def wrapper(*args, **kwds):
try:
return func(*args, **kwds)
except KeyError:
return None
return wrapper
class DBusInterface(ABC):
"""Handle D-Bus interface for hostname/system."""

View File

@ -0,0 +1,93 @@
"""Interface to systemd-timedate over D-Bus."""
from datetime import datetime
import logging
from typing import Any, Dict
from ..exceptions import DBusError, DBusInterfaceError
from ..utils.dt import utc_from_timestamp
from ..utils.gdbus import DBus
from .const import (
DBUS_ATTR_LOCALRTC,
DBUS_ATTR_NTP,
DBUS_ATTR_NTPSYNCHRONIZED,
DBUS_ATTR_TIMEUSEC,
DBUS_ATTR_TIMEZONE,
DBUS_NAME_TIMEDATE,
DBUS_OBJECT_TIMEDATE,
)
from .interface import DBusInterface, dbus_property
from .utils import dbus_connected
_LOGGER: logging.Logger = logging.getLogger(__name__)
class TimeDate(DBusInterface):
"""Timedate function handler."""
name = DBUS_NAME_TIMEDATE
def __init__(self) -> None:
"""Initialize Properties."""
self.properties: Dict[str, Any] = {}
@property
@dbus_property
def timezone(self) -> str:
"""Return host timezone."""
return self.properties[DBUS_ATTR_TIMEZONE]
@property
@dbus_property
def local_rtc(self) -> bool:
"""Return if a local RTC exists."""
return self.properties[DBUS_ATTR_LOCALRTC]
@property
@dbus_property
def ntp(self) -> bool:
"""Return if NTP is enabled."""
return self.properties[DBUS_ATTR_NTP]
@property
@dbus_property
def ntp_synchronized(self) -> bool:
"""Return if NTP is synchronized."""
return self.properties[DBUS_ATTR_NTPSYNCHRONIZED]
@property
@dbus_property
def dt_utc(self) -> datetime:
"""Return the system UTC time."""
return utc_from_timestamp(self.properties[DBUS_ATTR_TIMEUSEC] / 1000000)
async def connect(self):
"""Connect to D-Bus."""
try:
self.dbus = await DBus.connect(DBUS_NAME_TIMEDATE, DBUS_OBJECT_TIMEDATE)
except DBusError:
_LOGGER.warning("Can't connect to systemd-timedate")
except DBusInterfaceError:
_LOGGER.warning(
"No timedate support on the host. Time/Date functions have been disabled."
)
@dbus_connected
def set_time(self, utc: datetime):
"""Set time & date on host as UTC.
Return a coroutine.
"""
return self.dbus.SetTime(int(utc.timestamp() * 1000000), False, False)
@dbus_connected
def set_ntp(self, use_ntp: bool):
"""Turn NTP on or off.
Return a coroutine.
"""
return self.dbus.SetNTP(use_ntp)
@dbus_connected
async def update(self):
"""Update Properties."""
self.properties = await self.dbus.get_properties(DBUS_NAME_TIMEDATE)

View File

@ -112,7 +112,7 @@ class DockerAddon(DockerInterface):
return {
**addon_env,
ENV_TIME: self.sys_config.timezone,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.addon.supervisor_token,
ENV_TOKEN_HASSIO: self.addon.supervisor_token,
}

View File

@ -94,7 +94,7 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
ulimits=self.ulimits,
cpu_rt_runtime=self.cpu_rt_runtime,
device_cgroup_rules=self.cgroups_rules,
environment={ENV_TIME: self.sys_config.timezone},
environment={ENV_TIME: self.sys_timezone},
volumes=self.volumes,
)

View File

@ -51,7 +51,7 @@ class DockerCli(DockerInterface, CoreSysAttributes):
"observer": self.sys_docker.network.observer,
},
environment={
ENV_TIME: self.sys_config.timezone,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.sys_plugins.cli.supervisor_token,
},
)

View File

@ -45,7 +45,7 @@ class DockerDNS(DockerInterface, CoreSysAttributes):
hostname=self.name.replace("_", "-"),
detach=True,
security_opt=self.security_opt,
environment={ENV_TIME: self.sys_config.timezone},
environment={ENV_TIME: self.sys_timezone},
volumes={
str(self.sys_config.path_extern_dns): {"bind": "/config", "mode": "rw"}
},

View File

@ -143,7 +143,7 @@ class DockerHomeAssistant(DockerInterface):
environment={
"HASSIO": self.sys_docker.network.supervisor,
"SUPERVISOR": self.sys_docker.network.supervisor,
ENV_TIME: self.sys_config.timezone,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.sys_homeassistant.supervisor_token,
ENV_TOKEN_HASSIO: self.sys_homeassistant.supervisor_token,
},
@ -181,7 +181,7 @@ class DockerHomeAssistant(DockerInterface):
"mode": "ro",
},
},
environment={ENV_TIME: self.sys_config.timezone},
environment={ENV_TIME: self.sys_timezone},
)
def is_initialize(self) -> Awaitable[bool]:

View File

@ -53,7 +53,7 @@ class DockerMulticast(DockerInterface, CoreSysAttributes):
security_opt=self.security_opt,
cap_add=self.capabilities,
extra_hosts={"supervisor": self.sys_docker.network.supervisor},
environment={ENV_TIME: self.sys_config.timezone},
environment={ENV_TIME: self.sys_timezone},
)
self._meta = docker_container.attrs

View File

@ -48,7 +48,7 @@ class DockerObserver(DockerInterface, CoreSysAttributes):
restart_policy={"Name": "always"},
extra_hosts={"supervisor": self.sys_docker.network.supervisor},
environment={
ENV_TIME: self.sys_config.timezone,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.sys_plugins.observer.supervisor_token,
ENV_NETWORK_MASK: DOCKER_NETWORK_MASK,
},

View File

@ -352,6 +352,21 @@ class CodeNotaryBackendError(CodeNotaryError):
"""CodeNotary backend error happening."""
# util/whoami
class WhoamiError(HassioError):
"""Error while using whoami."""
class WhoamiSSLError(WhoamiError):
"""Error with the SSL certificate."""
class WhoamiConnectivityError(WhoamiError):
"""Connectivity errors while using whoami."""
# docker/api

View File

@ -82,6 +82,9 @@ class HostManager(CoreSysAttributes):
if self.sys_dbus.hostname.is_connected:
features.append(HostFeature.HOSTNAME)
if self.sys_dbus.timedate.is_connected:
features.append(HostFeature.TIMEDATE)
if self.sys_hassos.available:
features.append(HostFeature.HASSOS)
@ -89,8 +92,7 @@ class HostManager(CoreSysAttributes):
async def reload(self):
"""Reload host functions."""
if self.sys_dbus.hostname.is_connected:
await self.info.update()
await self.info.update()
if self.sys_dbus.systemd.is_connected:
await self.services.update()

View File

@ -1,14 +1,13 @@
"""Power control for host."""
from datetime import datetime
import logging
from ..const import HostFeature
from ..coresys import CoreSysAttributes
from ..exceptions import HostNotSupportedError
_LOGGER: logging.Logger = logging.getLogger(__name__)
MANAGER = "manager"
HOSTNAME = "hostname"
class SystemControl(CoreSysAttributes):
"""Handle host power controls."""
@ -17,21 +16,24 @@ class SystemControl(CoreSysAttributes):
"""Initialize host power handling."""
self.coresys = coresys
def _check_dbus(self, flag):
def _check_dbus(self, flag: HostFeature) -> None:
"""Check if systemd is connect or raise error."""
if flag == MANAGER and (
if flag in (HostFeature.SHUTDOWN, HostFeature.REBOOT) 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:
if flag == HostFeature.HOSTNAME and self.sys_dbus.hostname.is_connected:
return
if flag == HostFeature.TIMEDATE and self.sys_dbus.timedate.is_connected:
return
_LOGGER.error("No %s D-Bus connection available", flag)
raise HostNotSupportedError()
raise HostNotSupportedError(
f"No {flag!s} D-Bus connection available", _LOGGER.error
)
async def reboot(self):
async def reboot(self) -> None:
"""Reboot host system."""
self._check_dbus(MANAGER)
self._check_dbus(HostFeature.REBOOT)
use_logind = self.sys_dbus.logind.is_connected
_LOGGER.info(
@ -46,9 +48,9 @@ class SystemControl(CoreSysAttributes):
else:
await self.sys_dbus.systemd.reboot()
async def shutdown(self):
async def shutdown(self) -> None:
"""Shutdown host system."""
self._check_dbus(MANAGER)
self._check_dbus(HostFeature.SHUTDOWN)
use_logind = self.sys_dbus.logind.is_connected
_LOGGER.info(
@ -63,10 +65,18 @@ class SystemControl(CoreSysAttributes):
else:
await self.sys_dbus.systemd.power_off()
async def set_hostname(self, hostname):
async def set_hostname(self, hostname: str) -> None:
"""Set local a new Hostname."""
self._check_dbus(HOSTNAME)
self._check_dbus(HostFeature.HOSTNAME)
_LOGGER.info("Set hostname %s", hostname)
await self.sys_dbus.hostname.set_static_hostname(hostname)
await self.sys_host.info.update()
await self.sys_dbus.hostname.update()
async def set_datetime(self, new_time: datetime) -> None:
"""Update host clock with new (utc) datetime."""
self._check_dbus(HostFeature.TIMEDATE)
_LOGGER.info("Setting new host datetime: %s", new_time.isoformat())
await self.sys_dbus.timedate.set_time(new_time)
await self.sys_dbus.timedate.update()

View File

@ -1,15 +1,11 @@
"""Info control for host."""
import asyncio
from datetime import datetime
import logging
from typing import Optional
from ..coresys import CoreSysAttributes
from ..exceptions import (
DBusError,
DBusNotConnectedError,
HostError,
HostNotSupportedError,
)
from ..exceptions import DBusError, HostError
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -51,6 +47,31 @@ class InfoCenter(CoreSysAttributes):
"""Return local CPE."""
return self.sys_dbus.hostname.cpe
@property
def timezone(self) -> Optional[str]:
"""Return host timezone."""
return self.sys_dbus.timedate.timezone
@property
def dt_utc(self) -> Optional[datetime]:
"""Return host UTC time."""
return self.sys_dbus.timedate.dt_utc
@property
def use_rtc(self) -> Optional[bool]:
"""Return true if host have an RTC."""
return self.sys_dbus.timedate.local_rtc
@property
def use_ntp(self) -> Optional[bool]:
"""Return true if host using NTP."""
return self.sys_dbus.timedate.ntp
@property
def dt_synchronized(self) -> Optional[bool]:
"""Return true if host time is syncronized."""
return self.sys_dbus.timedate.ntp_synchronized
@property
def total_space(self) -> float:
"""Return total space (GiB) on disk for supervisor data directory."""
@ -98,9 +119,9 @@ class InfoCenter(CoreSysAttributes):
"""Update properties over dbus."""
_LOGGER.info("Updating local host information")
try:
await self.sys_dbus.hostname.update()
if self.sys_dbus.hostname.is_connected:
await self.sys_dbus.hostname.update()
if self.sys_dbus.timedate.is_connected:
await self.sys_dbus.timedate.update()
except DBusError:
_LOGGER.warning("Can't update host system information!")
except DBusNotConnectedError:
_LOGGER.error("No hostname D-Bus connection available")
raise HostNotSupportedError() from None

View File

@ -241,7 +241,7 @@ class Supervisor(CoreSysAttributes):
timeout = aiohttp.ClientTimeout(total=10)
try:
await self.sys_websession.head(
"http://version.home-assistant.io/online.txt", timeout=timeout
"https://version.home-assistant.io/online.txt", timeout=timeout
)
except (ClientError, asyncio.TimeoutError):
self.connectivity = False

View File

@ -1,18 +1,13 @@
"""Tools file for Supervisor."""
import asyncio
from contextlib import suppress
from datetime import datetime, timedelta, timezone, tzinfo
import logging
import re
from typing import Any, Dict, Optional
import zoneinfo
import aiohttp
import pytz
import ciso8601
UTC = pytz.utc
GEOIP_URL = "http://ip-api.com/json/"
_LOGGER: logging.Logger = logging.getLogger(__name__)
UTC = timezone.utc
# Copyright (c) Django Software Foundation and individual contributors.
@ -26,21 +21,6 @@ DATETIME_RE = re.compile(
)
async def fetch_timezone(websession: aiohttp.ClientSession):
"""Read timezone from freegeoip."""
data = {}
try:
async with websession.get(GEOIP_URL, timeout=10) as request:
data = await request.json()
except (aiohttp.ClientError, asyncio.TimeoutError) as err:
_LOGGER.warning("Can't fetch freegeoip data: %s", err)
except ValueError as err:
_LOGGER.warning("Error on parse freegeoip data: %s", err)
return data.get("timezone", "UTC")
# Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved.
# https://github.com/django/django/blob/master/LICENSE
@ -52,6 +32,9 @@ def parse_datetime(dt_str):
Raises ValueError if the input is well formatted but not a valid datetime.
Returns None if the input isn't well formatted.
"""
with suppress(ValueError, IndexError):
return ciso8601.parse_datetime(dt_str)
match = DATETIME_RE.match(dt_str)
if not match:
return None
@ -84,4 +67,12 @@ def utcnow() -> datetime:
def utc_from_timestamp(timestamp: float) -> datetime:
"""Return a UTC time from a timestamp."""
return UTC.localize(datetime.utcfromtimestamp(timestamp))
return datetime.utcfromtimestamp(timestamp).replace(tzinfo=UTC)
def get_time_zone(time_zone_str: str) -> Optional[tzinfo]:
"""Get time zone from string. Return None if unable to determine."""
try:
return zoneinfo.ZoneInfo(time_zone_str)
except zoneinfo.ZoneInfoNotFoundError:
return None

View File

@ -43,5 +43,5 @@ async def check_pwned_password(websession: aiohttp.ClientSession, sha1_pw: str)
except (aiohttp.ClientError, asyncio.TimeoutError) as err:
raise PwnedConnectivityError(
f"Can't fetch HIBP data: {err}", _LOGGER.warning
f"Can't fetch HIBP data: {str(err) or 'Timeout'}", _LOGGER.warning
) from err

View File

@ -1,8 +1,9 @@
"""Validate utils."""
import pytz
import voluptuous as vol
from .dt import get_time_zone
def schema_or(schema):
"""Allow schema or empty."""
@ -18,12 +19,9 @@ def schema_or(schema):
def validate_timezone(timezone):
"""Validate voluptuous timezone."""
try:
pytz.timezone(timezone)
except pytz.exceptions.UnknownTimeZoneError:
raise vol.Invalid(
"Invalid time zone passed in. Valid options can be found here: "
"http://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
) from None
return timezone
if get_time_zone(timezone) is not None:
return timezone
raise vol.Invalid(
"Invalid time zone passed in. Valid options can be found here: "
"http://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
) from None

View File

@ -0,0 +1,58 @@
"""Small wrapper for whoami API.
https://github.com/home-assistant/whoami.home-assistant.io
"""
import asyncio
from datetime import datetime
import logging
import aiohttp
import attr
from ..exceptions import WhoamiConnectivityError, WhoamiError, WhoamiSSLError
from .dt import utc_from_timestamp
_LOGGER: logging.Logger = logging.getLogger(__name__)
_API_CALL: str = "whoami.home-assistant.io/v1"
@attr.s(slots=True, frozen=True)
class WhoamiData:
"""Client Whoami data."""
timezone: str = attr.ib()
dt_utc: datetime = attr.ib()
async def retrieve_whoami(
websession: aiohttp.ClientSession, with_ssl: bool = True
) -> WhoamiData:
"""Check if password is pwned."""
url: str = f"http{'s' if with_ssl else ''}://{_API_CALL}"
_LOGGER.debug("Check whoami to verify connectivity/system with: %s", url)
try:
async with websession.get(
url, timeout=aiohttp.ClientTimeout(total=10)
) as request:
if request.status != 200:
raise WhoamiError(
f"Whoami service response with {request.status}", _LOGGER.warning
)
data = await request.json()
return WhoamiData(
data["timezone"], utc_from_timestamp(float(data["timestamp"]))
)
except aiohttp.ClientConnectorSSLError as err:
# Expired certificate / Date ISSUE
# pylint: disable=bad-exception-context
raise WhoamiSSLError(
f"Whoami service failed with SSL verification: {err!s}", _LOGGER.warning
) from err
except (aiohttp.ClientError, asyncio.TimeoutError) as err:
raise WhoamiConnectivityError(
f"Can't fetch Whoami data: {str(err) or 'Timeout'}", _LOGGER.warning
) from err

View File

@ -136,7 +136,7 @@ SCHEMA_UPDATER_CONFIG = vol.Schema(
# pylint: disable=no-value-for-parameter
SCHEMA_SUPERVISOR_CONFIG = vol.Schema(
{
vol.Optional(ATTR_TIMEZONE, default="UTC"): validate_timezone,
vol.Optional(ATTR_TIMEZONE): validate_timezone,
vol.Optional(ATTR_LAST_BOOT): vol.Coerce(str),
vol.Optional(
ATTR_VERSION, default=AwesomeVersion(SUPERVISOR_VERSION)

View File

@ -128,9 +128,6 @@ async def coresys(loop, docker, network_manager, aiohttp_client) -> CoreSys:
"""Create a CoreSys Mock."""
with patch("supervisor.bootstrap.initialize_system_data"), patch(
"supervisor.bootstrap.setup_diagnostics"
), patch(
"supervisor.bootstrap.fetch_timezone",
return_value="Europe/Zurich",
):
coresys_obj = await initialize_coresys()

View File

@ -0,0 +1,33 @@
"""Test hostname dbus interface."""
import pytest
from supervisor.coresys import CoreSys
from supervisor.exceptions import DBusNotConnectedError
async def test_dbus_hostname_info(coresys: CoreSys):
"""Test coresys dbus connection."""
assert coresys.dbus.hostname.hostname is None
await coresys.dbus.hostname.connect()
await coresys.dbus.hostname.update()
assert coresys.dbus.hostname.hostname == "homeassistant-n2"
assert coresys.dbus.hostname.kernel == "5.10.33"
assert (
coresys.dbus.hostname.cpe
== "cpe:2.3:o:home-assistant:haos:6.0.dev20210504:*:development:*:*:*:odroid-n2:*"
)
assert coresys.dbus.hostname.operating_system == "Home Assistant OS 6.0.dev20210504"
async def test_dbus_sethostname(coresys: CoreSys):
"""Set hostname on backend."""
with pytest.raises(DBusNotConnectedError):
await coresys.dbus.hostname.set_static_hostname("StarWars")
await coresys.dbus.hostname.connect()
await coresys.dbus.hostname.set_static_hostname("StarWars")

View File

@ -0,0 +1,45 @@
"""Test TimeDate dbus interface."""
from datetime import datetime, timezone
import pytest
from supervisor.coresys import CoreSys
from supervisor.exceptions import DBusNotConnectedError
async def test_dbus_timezone(coresys: CoreSys):
"""Test coresys dbus connection."""
assert coresys.dbus.timedate.dt_utc is None
await coresys.dbus.timedate.connect()
await coresys.dbus.timedate.update()
assert coresys.dbus.timedate.dt_utc == datetime(
2021, 5, 19, 8, 36, 54, 405718, tzinfo=timezone.utc
)
assert (
coresys.dbus.timedate.dt_utc.isoformat() == "2021-05-19T08:36:54.405718+00:00"
)
async def test_dbus_settime(coresys: CoreSys):
"""Set timestamp on backend."""
test_dt = datetime(2021, 5, 19, 8, 36, 54, 405718, tzinfo=timezone.utc)
with pytest.raises(DBusNotConnectedError):
await coresys.dbus.timedate.set_time(test_dt)
await coresys.dbus.timedate.connect()
await coresys.dbus.timedate.set_time(test_dt)
async def test_dbus_setntp(coresys: CoreSys):
"""Disable NTP on backend."""
with pytest.raises(DBusNotConnectedError):
await coresys.dbus.timedate.set_ntp(False)
await coresys.dbus.timedate.connect()
await coresys.dbus.timedate.set_ntp(False)

View File

@ -0,0 +1 @@
()

View File

@ -0,0 +1,15 @@
{
"Hostname": "homeassistant-n2",
"StaticHostname": "homeassistant-n2",
"PrettyHostname": "",
"IconName": "computer-embedded",
"Chassis": "embedded",
"Deployment": "development",
"Location": "",
"KernelName": "Linux",
"KernelRelease": "5.10.33",
"KernelVersion": "#1 SMP PREEMPT Wed May 5 00:55:38 UTC 2021",
"OperatingSystemPrettyName": "Home Assistant OS 6.0.dev20210504",
"OperatingSystemCPEName": "cpe:2.3:o:home-assistant:haos:6.0.dev20210504:*:development:*:*:*:odroid-n2:*",
"HomeURL": "https://hass.io/"
}

View File

@ -0,0 +1,102 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping"/>
<method name="GetMachineId">
<arg type="s" name="machine_uuid" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="data" type="s" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="properties" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
<interface name="org.freedesktop.hostname1">
<property name="Hostname" type="s" access="read">
</property>
<property name="StaticHostname" type="s" access="read">
</property>
<property name="PrettyHostname" type="s" access="read">
</property>
<property name="IconName" type="s" access="read">
</property>
<property name="Chassis" type="s" access="read">
</property>
<property name="Deployment" type="s" access="read">
</property>
<property name="Location" type="s" access="read">
</property>
<property name="KernelName" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KernelRelease" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KernelVersion" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="OperatingSystemPrettyName" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="OperatingSystemCPEName" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HomeURL" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<method name="SetHostname">
<arg type="s" name="hostname" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetStaticHostname">
<arg type="s" name="hostname" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetPrettyHostname">
<arg type="s" name="hostname" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetIconName">
<arg type="s" name="icon" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetChassis">
<arg type="s" name="chassis" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetDeployment">
<arg type="s" name="deployment" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetLocation">
<arg type="s" name="location" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="GetProductUUID">
<arg type="b" name="interactive" direction="in"/>
<arg type="ay" name="uuid" direction="out"/>
</method>
</interface>
</node>

View File

@ -0,0 +1,381 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping"/>
<method name="GetMachineId">
<arg type="s" name="machine_uuid" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="data" type="s" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="properties" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
<interface name="org.freedesktop.login1.Manager">
<property name="EnableWallMessages" type="b" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="WallMessage" type="s" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="NAutoVTs" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillOnlyUsers" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillExcludeUsers" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillUserProcesses" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RebootParameter" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="RebootToFirmwareSetup" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="RebootToBootLoaderMenu" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="RebootToBootLoaderEntry" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="BootLoaderEntries" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleHint" type="b" access="read">
</property>
<property name="IdleSinceHint" type="t" access="read">
</property>
<property name="IdleSinceHintMonotonic" type="t" access="read">
</property>
<property name="BlockInhibited" type="s" access="read">
</property>
<property name="DelayInhibited" type="s" access="read">
</property>
<property name="InhibitDelayMaxUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UserStopDelayUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandlePowerKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleSuspendKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleHibernateKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleLidSwitch" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleLidSwitchExternalPower" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleLidSwitchDocked" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HoldoffTimeoutUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleAction" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleActionUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="PreparingForShutdown" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="PreparingForSleep" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="ScheduledShutdown" type="(st)" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="Docked" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="LidClosed" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="OnExternalPower" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="RemoveIPC" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RuntimeDirectorySize" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RuntimeDirectoryInodesMax" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InhibitorsMax" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="NCurrentInhibitors" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="SessionsMax" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="NCurrentSessions" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<method name="GetSession">
<arg type="s" name="session_id" direction="in"/>
<arg type="o" name="object_path" direction="out"/>
</method>
<method name="GetSessionByPID">
<arg type="u" name="pid" direction="in"/>
<arg type="o" name="object_path" direction="out"/>
</method>
<method name="GetUser">
<arg type="u" name="uid" direction="in"/>
<arg type="o" name="object_path" direction="out"/>
</method>
<method name="GetUserByPID">
<arg type="u" name="pid" direction="in"/>
<arg type="o" name="object_path" direction="out"/>
</method>
<method name="GetSeat">
<arg type="s" name="seat_id" direction="in"/>
<arg type="o" name="object_path" direction="out"/>
</method>
<method name="ListSessions">
<arg type="a(susso)" name="sessions" direction="out"/>
</method>
<method name="ListUsers">
<arg type="a(uso)" name="users" direction="out"/>
</method>
<method name="ListSeats">
<arg type="a(so)" name="seats" direction="out"/>
</method>
<method name="ListInhibitors">
<arg type="a(ssssuu)" name="inhibitors" direction="out"/>
</method>
<method name="CreateSession">
<arg type="u" name="uid" direction="in"/>
<arg type="u" name="pid" direction="in"/>
<arg type="s" name="service" direction="in"/>
<arg type="s" name="type" direction="in"/>
<arg type="s" name="class" direction="in"/>
<arg type="s" name="desktop" direction="in"/>
<arg type="s" name="seat_id" direction="in"/>
<arg type="u" name="vtnr" direction="in"/>
<arg type="s" name="tty" direction="in"/>
<arg type="s" name="display" direction="in"/>
<arg type="b" name="remote" direction="in"/>
<arg type="s" name="remote_user" direction="in"/>
<arg type="s" name="remote_host" direction="in"/>
<arg type="a(sv)" name="properties" direction="in"/>
<arg type="s" name="session_id" direction="out"/>
<arg type="o" name="object_path" direction="out"/>
<arg type="s" name="runtime_path" direction="out"/>
<arg type="h" name="fifo_fd" direction="out"/>
<arg type="u" name="uid" direction="out"/>
<arg type="s" name="seat_id" direction="out"/>
<arg type="u" name="vtnr" direction="out"/>
<arg type="b" name="existing" direction="out"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="ReleaseSession">
<arg type="s" name="session_id" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="ActivateSession">
<arg type="s" name="session_id" direction="in"/>
</method>
<method name="ActivateSessionOnSeat">
<arg type="s" name="session_id" direction="in"/>
<arg type="s" name="seat_id" direction="in"/>
</method>
<method name="LockSession">
<arg type="s" name="session_id" direction="in"/>
</method>
<method name="UnlockSession">
<arg type="s" name="session_id" direction="in"/>
</method>
<method name="LockSessions">
</method>
<method name="UnlockSessions">
</method>
<method name="KillSession">
<arg type="s" name="session_id" direction="in"/>
<arg type="s" name="who" direction="in"/>
<arg type="i" name="signal_number" direction="in"/>
</method>
<method name="KillUser">
<arg type="u" name="uid" direction="in"/>
<arg type="i" name="signal_number" direction="in"/>
</method>
<method name="TerminateSession">
<arg type="s" name="session_id" direction="in"/>
</method>
<method name="TerminateUser">
<arg type="u" name="uid" direction="in"/>
</method>
<method name="TerminateSeat">
<arg type="s" name="seat_id" direction="in"/>
</method>
<method name="SetUserLinger">
<arg type="u" name="uid" direction="in"/>
<arg type="b" name="enable" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="AttachDevice">
<arg type="s" name="seat_id" direction="in"/>
<arg type="s" name="sysfs_path" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="FlushDevices">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="PowerOff">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="Reboot">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="Halt">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="Suspend">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="Hibernate">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="HybridSleep">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SuspendThenHibernate">
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="CanPowerOff">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanReboot">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanHalt">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanSuspend">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanHibernate">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanHybridSleep">
<arg type="s" name="result" direction="out"/>
</method>
<method name="CanSuspendThenHibernate">
<arg type="s" name="result" direction="out"/>
</method>
<method name="ScheduleShutdown">
<arg type="s" name="type" direction="in"/>
<arg type="t" name="usec" direction="in"/>
</method>
<method name="CancelScheduledShutdown">
<arg type="b" name="cancelled" direction="out"/>
</method>
<method name="Inhibit">
<arg type="s" name="what" direction="in"/>
<arg type="s" name="who" direction="in"/>
<arg type="s" name="why" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="h" name="pipe_fd" direction="out"/>
</method>
<method name="CanRebootParameter">
<arg type="s" name="result" direction="out"/>
</method>
<method name="SetRebootParameter">
<arg type="s" name="parameter" direction="in"/>
</method>
<method name="CanRebootToFirmwareSetup">
<arg type="s" name="result" direction="out"/>
</method>
<method name="SetRebootToFirmwareSetup">
<arg type="b" name="enable" direction="in"/>
</method>
<method name="CanRebootToBootLoaderMenu">
<arg type="s" name="result" direction="out"/>
</method>
<method name="SetRebootToBootLoaderMenu">
<arg type="t" name="timeout" direction="in"/>
</method>
<method name="CanRebootToBootLoaderEntry">
<arg type="s" name="result" direction="out"/>
</method>
<method name="SetRebootToBootLoaderEntry">
<arg type="s" name="boot_loader_entry" direction="in"/>
</method>
<method name="SetWallMessage">
<arg type="s" name="wall_message" direction="in"/>
<arg type="b" name="enable" direction="in"/>
</method>
<signal name="SessionNew">
<arg type="s" name="session_id"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="SessionRemoved">
<arg type="s" name="session_id"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="UserNew">
<arg type="u" name="uid"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="UserRemoved">
<arg type="u" name="uid"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="SeatNew">
<arg type="s" name="seat_id"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="SeatRemoved">
<arg type="s" name="seat_id"/>
<arg type="o" name="object_path"/>
</signal>
<signal name="PrepareForShutdown">
<arg type="b" name="start"/>
</signal>
<signal name="PrepareForSleep">
<arg type="b" name="start"/>
</signal>
</interface>
<node name="seat"/>
<node name="user"/>
<node name="session"/>
</node>

View File

@ -0,0 +1,726 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping"/>
<method name="GetMachineId">
<arg type="s" name="machine_uuid" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="data" type="s" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="properties" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
<interface name="org.freedesktop.systemd1.Manager">
<property name="Version" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Features" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Virtualization" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Architecture" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Tainted" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="FirmwareTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="FirmwareTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="LoaderTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="LoaderTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KernelTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KernelTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UserspaceTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UserspaceTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="FinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="FinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="SecurityStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="SecurityStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="SecurityFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="SecurityFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="GeneratorsStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="GeneratorsStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="GeneratorsFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="GeneratorsFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UnitsLoadStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UnitsLoadStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UnitsLoadFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="UnitsLoadFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDSecurityStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDSecurityStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDSecurityFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDSecurityFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDGeneratorsStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDGeneratorsStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDGeneratorsFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDGeneratorsFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDUnitsLoadStartTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDUnitsLoadStartTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDUnitsLoadFinishTimestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="InitRDUnitsLoadFinishTimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="LogLevel" type="s" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="LogTarget" type="s" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="NNames" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="NFailedUnits" type="u" access="read">
</property>
<property name="NJobs" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="NInstalledJobs" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="NFailedJobs" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="Progress" type="d" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="Environment" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="ConfirmSpawn" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="ShowStatus" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="UnitPath" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultStandardOutput" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultStandardError" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RuntimeWatchdogUSec" type="t" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="RebootWatchdogUSec" type="t" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="KExecWatchdogUSec" type="t" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="ServiceWatchdogs" type="b" access="readwrite">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</property>
<property name="ControlGroup" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="SystemState" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="ExitCode" type="y" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="DefaultTimerAccuracyUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultTimeoutStartUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultTimeoutStopUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultTimeoutAbortUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="DefaultRestartUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultStartLimitIntervalUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultStartLimitBurst" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultCPUAccounting" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultBlockIOAccounting" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultMemoryAccounting" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultTasksAccounting" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitCPU" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitCPUSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitFSIZE" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitFSIZESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitDATA" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitDATASoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitSTACK" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitSTACKSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitCORE" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitCORESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRSS" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRSSSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNOFILE" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNOFILESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitAS" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitASSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNPROC" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNPROCSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitMEMLOCK" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitMEMLOCKSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitLOCKS" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitLOCKSSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitSIGPENDING" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitSIGPENDINGSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitMSGQUEUE" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitMSGQUEUESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNICE" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitNICESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRTPRIO" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRTPRIOSoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRTTIME" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultLimitRTTIMESoft" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultTasksMax" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="TimerSlackNSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="DefaultOOMPolicy" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<method name="GetUnit">
<arg type="s" name="name" direction="in"/>
<arg type="o" name="unit" direction="out"/>
</method>
<method name="GetUnitByPID">
<arg type="u" name="pid" direction="in"/>
<arg type="o" name="unit" direction="out"/>
</method>
<method name="GetUnitByInvocationID">
<arg type="ay" name="invocation_id" direction="in"/>
<arg type="o" name="unit" direction="out"/>
</method>
<method name="GetUnitByControlGroup">
<arg type="s" name="cgroup" direction="in"/>
<arg type="o" name="unit" direction="out"/>
</method>
<method name="LoadUnit">
<arg type="s" name="name" direction="in"/>
<arg type="o" name="unit" direction="out"/>
</method>
<method name="StartUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="StartUnitReplace">
<arg type="s" name="old_unit" direction="in"/>
<arg type="s" name="new_unit" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="StopUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="ReloadUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="RestartUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="TryRestartUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="ReloadOrRestartUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="ReloadOrTryRestartUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="EnqueueUnitJob">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="job_type" direction="in"/>
<arg type="s" name="job_mode" direction="in"/>
<arg type="u" name="job_id" direction="out"/>
<arg type="o" name="job_path" direction="out"/>
<arg type="s" name="unit_id" direction="out"/>
<arg type="o" name="unit_path" direction="out"/>
<arg type="s" name="job_type" direction="out"/>
<arg type="a(uosos)" name="affected_jobs" direction="out"/>
</method>
<method name="KillUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="whom" direction="in"/>
<arg type="i" name="signal" direction="in"/>
</method>
<method name="CleanUnit">
<arg type="s" name="name" direction="in"/>
<arg type="as" name="mask" direction="in"/>
</method>
<method name="FreezeUnit">
<arg type="s" name="name" direction="in"/>
</method>
<method name="ThawUnit">
<arg type="s" name="name" direction="in"/>
</method>
<method name="ResetFailedUnit">
<arg type="s" name="name" direction="in"/>
</method>
<method name="SetUnitProperties">
<arg type="s" name="name" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="a(sv)" name="properties" direction="in"/>
</method>
<method name="RefUnit">
<arg type="s" name="name" direction="in"/>
</method>
<method name="UnrefUnit">
<arg type="s" name="name" direction="in"/>
</method>
<method name="StartTransientUnit">
<arg type="s" name="name" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="a(sv)" name="properties" direction="in"/>
<arg type="a(sa(sv))" name="aux" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="GetUnitProcesses">
<arg type="s" name="name" direction="in"/>
<arg type="a(sus)" name="processes" direction="out"/>
</method>
<method name="AttachProcessesToUnit">
<arg type="s" name="unit_name" direction="in"/>
<arg type="s" name="subcgroup" direction="in"/>
<arg type="au" name="pids" direction="in"/>
</method>
<method name="AbandonScope">
<arg type="s" name="name" direction="in"/>
</method>
<method name="GetJob">
<arg type="u" name="id" direction="in"/>
<arg type="o" name="job" direction="out"/>
</method>
<method name="GetJobAfter">
<arg type="u" name="id" direction="in"/>
<arg type="a(usssoo)" name="jobs" direction="out"/>
</method>
<method name="GetJobBefore">
<arg type="u" name="id" direction="in"/>
<arg type="a(usssoo)" name="jobs" direction="out"/>
</method>
<method name="CancelJob">
<arg type="u" name="id" direction="in"/>
</method>
<method name="ClearJobs">
</method>
<method name="ResetFailed">
</method>
<method name="SetShowStatus">
<arg type="s" name="mode" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="ListUnits">
<arg type="a(ssssssouso)" name="units" direction="out"/>
</method>
<method name="ListUnitsFiltered">
<arg type="as" name="states" direction="in"/>
<arg type="a(ssssssouso)" name="units" direction="out"/>
</method>
<method name="ListUnitsByPatterns">
<arg type="as" name="states" direction="in"/>
<arg type="as" name="patterns" direction="in"/>
<arg type="a(ssssssouso)" name="units" direction="out"/>
</method>
<method name="ListUnitsByNames">
<arg type="as" name="names" direction="in"/>
<arg type="a(ssssssouso)" name="units" direction="out"/>
</method>
<method name="ListJobs">
<arg type="a(usssoo)" name="jobs" direction="out"/>
</method>
<method name="Subscribe">
</method>
<method name="Unsubscribe">
</method>
<method name="Dump">
<arg type="s" name="output" direction="out"/>
</method>
<method name="DumpByFileDescriptor">
<arg type="h" name="fd" direction="out"/>
</method>
<method name="Reload">
</method>
<method name="Reexecute">
</method>
<method name="Exit">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="Reboot">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="PowerOff">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="Halt">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="KExec">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="SwitchRoot">
<arg type="s" name="new_root" direction="in"/>
<arg type="s" name="init" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="SetEnvironment">
<arg type="as" name="assignments" direction="in"/>
</method>
<method name="UnsetEnvironment">
<arg type="as" name="names" direction="in"/>
</method>
<method name="UnsetAndSetEnvironment">
<arg type="as" name="names" direction="in"/>
<arg type="as" name="assignments" direction="in"/>
</method>
<method name="ListUnitFiles">
<arg type="a(ss)" name="unit_files" direction="out"/>
</method>
<method name="ListUnitFilesByPatterns">
<arg type="as" name="states" direction="in"/>
<arg type="as" name="patterns" direction="in"/>
<arg type="a(ss)" name="unit_files" direction="out"/>
</method>
<method name="GetUnitFileState">
<arg type="s" name="file" direction="in"/>
<arg type="s" name="state" direction="out"/>
</method>
<method name="EnableUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="b" name="carries_install_info" direction="out"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="DisableUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="EnableUnitFilesWithFlags">
<arg type="as" name="files" direction="in"/>
<arg type="t" name="flags" direction="in"/>
<arg type="b" name="carries_install_info" direction="out"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="DisableUnitFilesWithFlags">
<arg type="as" name="files" direction="in"/>
<arg type="t" name="flags" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="ReenableUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="b" name="carries_install_info" direction="out"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="LinkUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="PresetUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="b" name="carries_install_info" direction="out"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="PresetUnitFilesWithMode">
<arg type="as" name="files" direction="in"/>
<arg type="s" name="mode" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="b" name="carries_install_info" direction="out"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="MaskUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="UnmaskUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="RevertUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="SetDefaultTarget">
<arg type="s" name="name" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="GetDefaultTarget">
<arg type="s" name="name" direction="out"/>
</method>
<method name="PresetAllUnitFiles">
<arg type="s" name="mode" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="AddDependencyUnitFiles">
<arg type="as" name="files" direction="in"/>
<arg type="s" name="target" direction="in"/>
<arg type="s" name="type" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="b" name="force" direction="in"/>
<arg type="a(sss)" name="changes" direction="out"/>
</method>
<method name="GetUnitFileLinks">
<arg type="s" name="name" direction="in"/>
<arg type="b" name="runtime" direction="in"/>
<arg type="as" name="links" direction="out"/>
</method>
<method name="SetExitCode">
<arg type="y" name="number" direction="in"/>
</method>
<method name="LookupDynamicUserByName">
<arg type="s" name="name" direction="in"/>
<arg type="u" name="uid" direction="out"/>
</method>
<method name="LookupDynamicUserByUID">
<arg type="u" name="uid" direction="in"/>
<arg type="s" name="name" direction="out"/>
</method>
<method name="GetDynamicUsers">
<arg type="a(us)" name="users" direction="out"/>
</method>
<signal name="UnitNew">
<arg type="s" name="id"/>
<arg type="o" name="unit"/>
</signal>
<signal name="UnitRemoved">
<arg type="s" name="id"/>
<arg type="o" name="unit"/>
</signal>
<signal name="JobNew">
<arg type="u" name="id"/>
<arg type="o" name="job"/>
<arg type="s" name="unit"/>
</signal>
<signal name="JobRemoved">
<arg type="u" name="id"/>
<arg type="o" name="job"/>
<arg type="s" name="unit"/>
<arg type="s" name="result"/>
</signal>
<signal name="StartupFinished">
<arg type="t" name="firmware"/>
<arg type="t" name="loader"/>
<arg type="t" name="kernel"/>
<arg type="t" name="initrd"/>
<arg type="t" name="userspace"/>
<arg type="t" name="total"/>
</signal>
<signal name="UnitFilesChanged">
</signal>
<signal name="Reloading">
<arg type="b" name="active"/>
</signal>
</interface>
<node name="unit"/>
<node name="job"/>
</node>

View File

@ -0,0 +1 @@
()

View File

@ -0,0 +1 @@
()

View File

@ -0,0 +1,9 @@
{
"Timezone": "Etc/UTC",
"LocalRTC": false,
"CanNTP": true,
"NTP": true,
"NTPSynchronized": true,
"TimeUSec": 1621413414405718,
"RTCTimeUSec": 1621413415000000
}

View File

@ -0,0 +1,77 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Peer">
<method name="Ping"/>
<method name="GetMachineId">
<arg type="s" name="machine_uuid" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="data" type="s" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="properties" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg type="s" name="interface"/>
<arg type="a{sv}" name="changed_properties"/>
<arg type="as" name="invalidated_properties"/>
</signal>
</interface>
<interface name="org.freedesktop.timedate1">
<property name="Timezone" type="s" access="read">
</property>
<property name="LocalRTC" type="b" access="read">
</property>
<property name="CanNTP" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="NTP" type="b" access="read">
</property>
<property name="NTPSynchronized" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="TimeUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="RTCTimeUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<method name="SetTime">
<arg type="x" name="usec_utc" direction="in"/>
<arg type="b" name="relative" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetTimezone">
<arg type="s" name="timezone" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetLocalRTC">
<arg type="b" name="local_rtc" direction="in"/>
<arg type="b" name="fix_system" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="SetNTP">
<arg type="b" name="use_ntp" direction="in"/>
<arg type="b" name="interactive" direction="in"/>
</method>
<method name="ListTimezones">
<arg type="as" name="timezones" direction="out"/>
</method>
</interface>
</node>

View File

@ -1,9 +1,10 @@
"""Testing handling with CoreState."""
from supervisor.const import CoreState
from supervisor.coresys import CoreSys
def test_write_state(run_dir, coresys):
def test_write_state(run_dir, coresys: CoreSys):
"""Test write corestate to /run/supervisor."""
coresys.core.state = CoreState.RUNNING

17
tests/test_coresys.py Normal file
View File

@ -0,0 +1,17 @@
"""Testing handling with CoreState."""
from supervisor.coresys import CoreSys
async def test_timezone(run_dir, coresys: CoreSys):
"""Test write corestate to /run/supervisor."""
assert coresys.timezone == "UTC"
assert coresys.config.timezone is None
await coresys.dbus.timedate.connect()
await coresys.dbus.timedate.update()
assert coresys.timezone == "Etc/UTC"
coresys.config.timezone = "Europe/Zurich"
assert coresys.timezone == "Europe/Zurich"