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 awesomeversion==21.5.0
brotli==1.0.9 brotli==1.0.9
cchardet==2.1.7 cchardet==2.1.7
ciso8601==2.1.3
colorlog==5.0.1 colorlog==5.0.1
cpe==1.2.1 cpe==1.2.1
cryptography==3.4.6 cryptography==3.4.6
@ -13,7 +14,6 @@ docker==5.0.0
gitpython==3.1.17 gitpython==3.1.17
jinja2==3.0.1 jinja2==3.0.1
pulsectl==21.5.17 pulsectl==21.5.17
pytz==2021.1
pyudev==0.22.0 pyudev==0.22.0
ruamel.yaml==0.15.100 ruamel.yaml==0.15.100
sentry-sdk==1.1.0 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_OPERATING_SYSTEM,
ATTR_SERVICES, ATTR_SERVICES,
ATTR_STATE, ATTR_STATE,
ATTR_TIMEZONE,
CONTENT_TYPE_BINARY, CONTENT_TYPE_BINARY,
) )
from ..coresys import CoreSysAttributes 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 from .utils import api_process, api_process_raw, api_validate
SERVICE = "service" SERVICE = "service"
@ -49,6 +51,11 @@ class APIHost(CoreSysAttributes):
ATTR_HOSTNAME: self.sys_host.info.hostname, ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_KERNEL: self.sys_host.info.kernel, ATTR_KERNEL: self.sys_host.info.kernel,
ATTR_OPERATING_SYSTEM: self.sys_host.info.operating_system, 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 @api_process

View File

@ -48,5 +48,5 @@ class APIInfo(CoreSysAttributes):
ATTR_SUPPORTED: self.sys_core.supported, ATTR_SUPPORTED: self.sys_core.supported,
ATTR_CHANNEL: self.sys_updater.channel, ATTR_CHANNEL: self.sys_updater.channel,
ATTR_LOGGING: self.sys_config.logging, 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 .store import StoreManager
from .supervisor import Supervisor from .supervisor import Supervisor
from .updater import Updater from .updater import Updater
from .utils.dt import fetch_timezone
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -95,10 +94,6 @@ async def initialize_coresys() -> CoreSys:
if MACHINE_ID.exists(): if MACHINE_ID.exists():
coresys.machine_id = MACHINE_ID.read_text().strip() 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 # Set machine type
if os.environ.get(ENV_SUPERVISOR_MACHINE): if os.environ.get(ENV_SUPERVISOR_MACHINE):
coresys.machine = os.environ[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() 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): class CoreConfig(FileConfiguration):
"""Hold all core config data.""" """Hold all core config data."""
@ -57,13 +62,19 @@ class CoreConfig(FileConfiguration):
super().__init__(FILE_HASSIO_CONFIG, SCHEMA_SUPERVISOR_CONFIG) super().__init__(FILE_HASSIO_CONFIG, SCHEMA_SUPERVISOR_CONFIG)
@property @property
def timezone(self) -> str: def timezone(self) -> Optional[str]:
"""Return system timezone.""" """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 @timezone.setter
def timezone(self, value: str) -> None: def timezone(self, value: str) -> None:
"""Set system timezone.""" """Set system timezone."""
if value == _UTC:
return
self._data[ATTR_TIMEZONE] = value self._data[ATTR_TIMEZONE] = value
@property @property

View File

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

View File

@ -1,6 +1,7 @@
"""Main file for Supervisor.""" """Main file for Supervisor."""
import asyncio import asyncio
from contextlib import suppress from contextlib import suppress
from datetime import timedelta
import logging import logging
from typing import Awaitable, List, Optional from typing import Awaitable, List, Optional
@ -13,9 +14,13 @@ from .exceptions import (
HomeAssistantCrashError, HomeAssistantCrashError,
HomeAssistantError, HomeAssistantError,
SupervisorUpdateError, SupervisorUpdateError,
WhoamiError,
WhoamiSSLError,
) )
from .homeassistant.core import LANDINGPAGE from .homeassistant.core import LANDINGPAGE
from .resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason 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__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -109,6 +114,8 @@ class Core(CoreSysAttributes):
self.sys_dbus.load(), self.sys_dbus.load(),
# Load Host # Load Host
self.sys_host.load(), self.sys_host.load(),
# Adjust timezone / time settings
self._adjust_system_datetime(),
# Load Plugins container # Load Plugins container
self.sys_plugins.load(), self.sys_plugins.load(),
# load last available data # 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.last_boot = self.sys_hardware.helper.last_boot
self.sys_config.save_data() 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): async def repair(self):
"""Repair system integrity.""" """Repair system integrity."""
_LOGGER.info("Starting repair of Supervisor Environment") _LOGGER.info("Starting repair of Supervisor Environment")

View File

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

View File

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

View File

@ -19,6 +19,7 @@ DBUS_NAME_NM_CONNECTION_ACTIVE_CHANGED = (
) )
DBUS_NAME_SYSTEMD = "org.freedesktop.systemd1" DBUS_NAME_SYSTEMD = "org.freedesktop.systemd1"
DBUS_NAME_LOGIND = "org.freedesktop.login1" DBUS_NAME_LOGIND = "org.freedesktop.login1"
DBUS_NAME_TIMEDATE = "org.freedesktop.timedate1"
DBUS_OBJECT_BASE = "/" DBUS_OBJECT_BASE = "/"
DBUS_OBJECT_DNS = "/org/freedesktop/NetworkManager/DnsManager" 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_NM = "/org/freedesktop/NetworkManager"
DBUS_OBJECT_SYSTEMD = "/org/freedesktop/systemd1" DBUS_OBJECT_SYSTEMD = "/org/freedesktop/systemd1"
DBUS_OBJECT_LOGIND = "/org/freedesktop/login1" DBUS_OBJECT_LOGIND = "/org/freedesktop/login1"
DBUS_OBJECT_TIMEDATE = "/org/freedesktop/timedate1"
DBUS_ATTR_ACTIVE_CONNECTIONS = "ActiveConnections" DBUS_ATTR_ACTIVE_CONNECTIONS = "ActiveConnections"
DBUS_ATTR_ACTIVE_CONNECTION = "ActiveConnection" DBUS_ATTR_ACTIVE_CONNECTION = "ActiveConnection"
@ -70,6 +72,11 @@ DBUS_ATTR_VARIANT = "Variant"
DBUS_ATTR_VERSION = "Version" DBUS_ATTR_VERSION = "Version"
DBUS_ATTR_MANAGED = "Managed" DBUS_ATTR_MANAGED = "Managed"
DBUS_ATTR_CONNECTION_ENABLED = "ConnectivityCheckEnabled" 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): class RaucState(str, Enum):

View File

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

View File

@ -1,10 +1,24 @@
"""Interface class for D-Bus wrappers.""" """Interface class for D-Bus wrappers."""
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from functools import wraps
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from ..utils.gdbus import DBus 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): class DBusInterface(ABC):
"""Handle D-Bus interface for hostname/system.""" """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 { return {
**addon_env, **addon_env,
ENV_TIME: self.sys_config.timezone, ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.addon.supervisor_token, ENV_TOKEN: self.addon.supervisor_token,
ENV_TOKEN_HASSIO: self.addon.supervisor_token, ENV_TOKEN_HASSIO: self.addon.supervisor_token,
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -53,7 +53,7 @@ class DockerMulticast(DockerInterface, CoreSysAttributes):
security_opt=self.security_opt, security_opt=self.security_opt,
cap_add=self.capabilities, cap_add=self.capabilities,
extra_hosts={"supervisor": self.sys_docker.network.supervisor}, 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 self._meta = docker_container.attrs

View File

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

View File

@ -352,6 +352,21 @@ class CodeNotaryBackendError(CodeNotaryError):
"""CodeNotary backend error happening.""" """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 # docker/api

View File

@ -82,6 +82,9 @@ class HostManager(CoreSysAttributes):
if self.sys_dbus.hostname.is_connected: if self.sys_dbus.hostname.is_connected:
features.append(HostFeature.HOSTNAME) features.append(HostFeature.HOSTNAME)
if self.sys_dbus.timedate.is_connected:
features.append(HostFeature.TIMEDATE)
if self.sys_hassos.available: if self.sys_hassos.available:
features.append(HostFeature.HASSOS) features.append(HostFeature.HASSOS)
@ -89,7 +92,6 @@ class HostManager(CoreSysAttributes):
async def reload(self): async def reload(self):
"""Reload host functions.""" """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: if self.sys_dbus.systemd.is_connected:

View File

@ -1,14 +1,13 @@
"""Power control for host.""" """Power control for host."""
from datetime import datetime
import logging import logging
from ..const import HostFeature
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import HostNotSupportedError from ..exceptions import HostNotSupportedError
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
MANAGER = "manager"
HOSTNAME = "hostname"
class SystemControl(CoreSysAttributes): class SystemControl(CoreSysAttributes):
"""Handle host power controls.""" """Handle host power controls."""
@ -17,21 +16,24 @@ class SystemControl(CoreSysAttributes):
"""Initialize host power handling.""" """Initialize host power handling."""
self.coresys = coresys self.coresys = coresys
def _check_dbus(self, flag): def _check_dbus(self, flag: HostFeature) -> None:
"""Check if systemd is connect or raise error.""" """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 self.sys_dbus.systemd.is_connected or self.sys_dbus.logind.is_connected
): ):
return 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 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.""" """Reboot host system."""
self._check_dbus(MANAGER) self._check_dbus(HostFeature.REBOOT)
use_logind = self.sys_dbus.logind.is_connected use_logind = self.sys_dbus.logind.is_connected
_LOGGER.info( _LOGGER.info(
@ -46,9 +48,9 @@ class SystemControl(CoreSysAttributes):
else: else:
await self.sys_dbus.systemd.reboot() await self.sys_dbus.systemd.reboot()
async def shutdown(self): async def shutdown(self) -> None:
"""Shutdown host system.""" """Shutdown host system."""
self._check_dbus(MANAGER) self._check_dbus(HostFeature.SHUTDOWN)
use_logind = self.sys_dbus.logind.is_connected use_logind = self.sys_dbus.logind.is_connected
_LOGGER.info( _LOGGER.info(
@ -63,10 +65,18 @@ class SystemControl(CoreSysAttributes):
else: else:
await self.sys_dbus.systemd.power_off() 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.""" """Set local a new Hostname."""
self._check_dbus(HOSTNAME) self._check_dbus(HostFeature.HOSTNAME)
_LOGGER.info("Set hostname %s", hostname) _LOGGER.info("Set hostname %s", hostname)
await self.sys_dbus.hostname.set_static_hostname(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.""" """Info control for host."""
import asyncio import asyncio
from datetime import datetime
import logging import logging
from typing import Optional from typing import Optional
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import ( from ..exceptions import DBusError, HostError
DBusError,
DBusNotConnectedError,
HostError,
HostNotSupportedError,
)
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@ -51,6 +47,31 @@ class InfoCenter(CoreSysAttributes):
"""Return local CPE.""" """Return local CPE."""
return self.sys_dbus.hostname.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 @property
def total_space(self) -> float: def total_space(self) -> float:
"""Return total space (GiB) on disk for supervisor data directory.""" """Return total space (GiB) on disk for supervisor data directory."""
@ -98,9 +119,9 @@ class InfoCenter(CoreSysAttributes):
"""Update properties over dbus.""" """Update properties over dbus."""
_LOGGER.info("Updating local host information") _LOGGER.info("Updating local host information")
try: try:
if self.sys_dbus.hostname.is_connected:
await self.sys_dbus.hostname.update() await self.sys_dbus.hostname.update()
if self.sys_dbus.timedate.is_connected:
await self.sys_dbus.timedate.update()
except DBusError: except DBusError:
_LOGGER.warning("Can't update host system information!") _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) timeout = aiohttp.ClientTimeout(total=10)
try: try:
await self.sys_websession.head( 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): except (ClientError, asyncio.TimeoutError):
self.connectivity = False self.connectivity = False

View File

@ -1,18 +1,13 @@
"""Tools file for Supervisor.""" """Tools file for Supervisor."""
import asyncio from contextlib import suppress
from datetime import datetime, timedelta, timezone, tzinfo from datetime import datetime, timedelta, timezone, tzinfo
import logging
import re import re
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
import zoneinfo
import aiohttp import ciso8601
import pytz
UTC = pytz.utc UTC = timezone.utc
GEOIP_URL = "http://ip-api.com/json/"
_LOGGER: logging.Logger = logging.getLogger(__name__)
# Copyright (c) Django Software Foundation and individual contributors. # 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. # Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved. # All rights reserved.
# https://github.com/django/django/blob/master/LICENSE # 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. Raises ValueError if the input is well formatted but not a valid datetime.
Returns None if the input isn't well formatted. 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) match = DATETIME_RE.match(dt_str)
if not match: if not match:
return None return None
@ -84,4 +67,12 @@ def utcnow() -> datetime:
def utc_from_timestamp(timestamp: float) -> datetime: def utc_from_timestamp(timestamp: float) -> datetime:
"""Return a UTC time from a timestamp.""" """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: except (aiohttp.ClientError, asyncio.TimeoutError) as err:
raise PwnedConnectivityError( 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 ) from err

View File

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

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 # pylint: disable=no-value-for-parameter
SCHEMA_SUPERVISOR_CONFIG = vol.Schema( 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_LAST_BOOT): vol.Coerce(str),
vol.Optional( vol.Optional(
ATTR_VERSION, default=AwesomeVersion(SUPERVISOR_VERSION) 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.""" """Create a CoreSys Mock."""
with patch("supervisor.bootstrap.initialize_system_data"), patch( with patch("supervisor.bootstrap.initialize_system_data"), patch(
"supervisor.bootstrap.setup_diagnostics" "supervisor.bootstrap.setup_diagnostics"
), patch(
"supervisor.bootstrap.fetch_timezone",
return_value="Europe/Zurich",
): ):
coresys_obj = await initialize_coresys() 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.""" """Testing handling with CoreState."""
from supervisor.const import 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.""" """Test write corestate to /run/supervisor."""
coresys.core.state = CoreState.RUNNING 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"