mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-06-22 01:46:29 +00:00
Improve gdbus error handling (#1252)
* Improve gdbus error handling * Fix logging type * Detect no dbus * Fix issue with complex * Update hassio/dbus/__init__.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/hostname.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/rauc.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/systemd.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Fix black
This commit is contained in:
parent
e8cc85c487
commit
c0e3ccdb83
@ -6,7 +6,7 @@ import sys
|
||||
|
||||
from hassio import bootstrap
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def initialize_event_loop():
|
||||
|
@ -19,7 +19,7 @@ from ..store.addon import AddonStore
|
||||
from .addon import Addon
|
||||
from .data import AddonsData
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
AnyAddon = Union[Addon, AddonStore]
|
||||
|
||||
|
@ -55,7 +55,7 @@ from .model import AddonModel, Data
|
||||
from .utils import remove_data
|
||||
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
RE_WEBUI = re.compile(
|
||||
r"^(?:(?P<s_prefix>https?)|\[PROTO:(?P<t_proto>\w+)\])"
|
||||
|
@ -17,7 +17,7 @@ from ..store.addon import AddonStore
|
||||
from .addon import Addon
|
||||
from .validate import SCHEMA_ADDONS_FILE
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
Config = Dict[str, Any]
|
||||
|
||||
|
@ -22,7 +22,7 @@ from ..const import (
|
||||
if TYPE_CHECKING:
|
||||
from .model import AddonModel
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def rating_security(addon: AddonModel) -> int:
|
||||
|
@ -95,7 +95,7 @@ from ..validate import (
|
||||
UUID_MATCH,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
RE_VOLUME = re.compile(r"^(config|ssl|addons|backup|share)(?::(rw|ro))?$")
|
||||
|
@ -22,7 +22,7 @@ from .services import APIServices
|
||||
from .snapshots import APISnapshots
|
||||
from .supervisor import APISupervisor
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RestAPI(CoreSysAttributes):
|
||||
|
@ -94,7 +94,7 @@ from ..exceptions import APIError
|
||||
from ..validate import ALSA_DEVICE, DOCKER_PORTS
|
||||
from .utils import api_process, api_process_raw, api_validate
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
|
||||
|
||||
|
@ -10,7 +10,7 @@ from ..const import REQUEST_FROM, CONTENT_TYPE_JSON, CONTENT_TYPE_URL
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import APIForbidden
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIAuth(CoreSysAttributes):
|
||||
|
@ -26,7 +26,7 @@ from ..exceptions import APIError
|
||||
from ..validate import DNS_SERVER_LIST
|
||||
from .utils import api_process, api_process_raw, api_validate
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_SERVERS): DNS_SERVER_LIST})
|
||||
|
@ -12,7 +12,7 @@ from ..const import (
|
||||
)
|
||||
from ..coresys import CoreSysAttributes
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIHardware(CoreSysAttributes):
|
||||
|
@ -16,7 +16,7 @@ from ..const import (
|
||||
from ..coresys import CoreSysAttributes
|
||||
from .utils import api_process, api_validate
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
|
||||
|
||||
|
@ -36,7 +36,7 @@ from ..exceptions import APIError
|
||||
from ..validate import DOCKER_IMAGE, NETWORK_PORT
|
||||
from .utils import api_process, api_process_raw, api_validate
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
SCHEMA_OPTIONS = vol.Schema(
|
||||
|
@ -20,7 +20,7 @@ from ..const import (
|
||||
)
|
||||
from ..coresys import CoreSysAttributes
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
SERVICE = "service"
|
||||
|
||||
|
@ -19,7 +19,7 @@ from ..const import (
|
||||
from ..coresys import CoreSysAttributes
|
||||
from .utils import api_process
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIInfo(CoreSysAttributes):
|
||||
|
@ -28,7 +28,7 @@ from ..const import (
|
||||
from ..coresys import CoreSysAttributes
|
||||
from .utils import api_process
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIIngress(CoreSysAttributes):
|
||||
|
@ -14,7 +14,7 @@ from ..const import HEADER_HA_ACCESS
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIProxy(CoreSysAttributes):
|
||||
|
@ -16,7 +16,7 @@ from ..const import (
|
||||
)
|
||||
from ..coresys import CoreSysAttributes
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# fmt: off
|
||||
|
||||
|
@ -28,7 +28,7 @@ from ..const import (
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import APIError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
|
@ -44,7 +44,7 @@ from ..utils.validate import validate_timezone
|
||||
from ..validate import CHANNELS, LOG_LEVEL, REPOSITORIES, WAIT_BOOT
|
||||
from .utils import api_process, api_process_raw, api_validate
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
SCHEMA_OPTIONS = vol.Schema(
|
||||
|
@ -16,7 +16,7 @@ from ..const import (
|
||||
)
|
||||
from ..exceptions import HassioError, APIError, APIForbidden
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def json_loads(data):
|
||||
|
@ -8,7 +8,7 @@ from .coresys import CoreSys, CoreSysAttributes
|
||||
from .exceptions import HassioArchNotFound, JsonFileError
|
||||
from .utils.json import read_json_file
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
ARCH_JSON: Path = Path(__file__).parent.joinpath("data/arch.json")
|
||||
|
||||
|
@ -8,7 +8,7 @@ from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_AUTH_CONFIG
|
||||
from .exceptions import AuthError, HomeAssistantAPIError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Auth(JsonConfig, CoreSysAttributes):
|
||||
|
@ -29,7 +29,7 @@ from .tasks import Tasks
|
||||
from .updater import Updater
|
||||
from .utils.dt import fetch_timezone
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
ENV_SHARE = "SUPERVISOR_SHARE"
|
||||
ENV_NAME = "SUPERVISOR_NAME"
|
||||
|
@ -19,7 +19,7 @@ from .utils.dt import parse_datetime
|
||||
from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_HASSIO_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
HOMEASSISTANT_CONFIG = PurePath("homeassistant")
|
||||
|
||||
|
@ -14,7 +14,7 @@ from .const import (
|
||||
)
|
||||
from .exceptions import HassioError, HomeAssistantError, SupervisorUpdateError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HassIO(CoreSysAttributes):
|
||||
|
@ -1,39 +1,49 @@
|
||||
"""D-Bus interface objects."""
|
||||
import logging
|
||||
|
||||
from .systemd import Systemd
|
||||
from .hostname import Hostname
|
||||
from .rauc import Rauc
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..coresys import CoreSysAttributes, CoreSys
|
||||
from ..exceptions import DBusNotConnectedError
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DBusManager(CoreSysAttributes):
|
||||
"""A DBus Interface handler."""
|
||||
|
||||
def __init__(self, coresys):
|
||||
def __init__(self, coresys: CoreSys) -> None:
|
||||
"""Initialize D-Bus interface."""
|
||||
self.coresys = coresys
|
||||
self.coresys: CoreSys = coresys
|
||||
|
||||
self._systemd = Systemd()
|
||||
self._hostname = Hostname()
|
||||
self._rauc = Rauc()
|
||||
self._systemd: Systemd = Systemd()
|
||||
self._hostname: Hostname = Hostname()
|
||||
self._rauc: Rauc = Rauc()
|
||||
|
||||
@property
|
||||
def systemd(self):
|
||||
def systemd(self) -> Systemd:
|
||||
"""Return the systemd interface."""
|
||||
return self._systemd
|
||||
|
||||
@property
|
||||
def hostname(self):
|
||||
def hostname(self) -> Hostname:
|
||||
"""Return the hostname interface."""
|
||||
return self._hostname
|
||||
|
||||
@property
|
||||
def rauc(self):
|
||||
def rauc(self) -> Rauc:
|
||||
"""Return the rauc interface."""
|
||||
return self._rauc
|
||||
|
||||
async def load(self):
|
||||
async def load(self) -> None:
|
||||
"""Connect interfaces to D-Bus."""
|
||||
|
||||
try:
|
||||
await self.systemd.connect()
|
||||
await self.hostname.connect()
|
||||
await self.rauc.connect()
|
||||
except DBusNotConnectedError:
|
||||
_LOGGER.error(
|
||||
"No DBus support from Host. Disabled any kind of host control!"
|
||||
)
|
||||
|
@ -3,10 +3,10 @@ import logging
|
||||
|
||||
from .interface import DBusInterface
|
||||
from .utils import dbus_connected
|
||||
from ..exceptions import DBusError
|
||||
from ..exceptions import DBusError, DBusInterfaceError
|
||||
from ..utils.gdbus import DBus
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
DBUS_NAME = "org.freedesktop.hostname1"
|
||||
DBUS_OBJECT = "/org/freedesktop/hostname1"
|
||||
@ -21,6 +21,10 @@ class Hostname(DBusInterface):
|
||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||
except DBusError:
|
||||
_LOGGER.warning("Can't connect to hostname")
|
||||
except DBusInterfaceError:
|
||||
_LOGGER.warning(
|
||||
"No hostname support on the host. Hostname functions have been disabled."
|
||||
)
|
||||
|
||||
@dbus_connected
|
||||
def set_static_hostname(self, hostname):
|
||||
|
@ -3,10 +3,10 @@ import logging
|
||||
|
||||
from .interface import DBusInterface
|
||||
from .utils import dbus_connected
|
||||
from ..exceptions import DBusError
|
||||
from ..exceptions import DBusError, DBusInterfaceError
|
||||
from ..utils.gdbus import DBus
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
DBUS_NAME = "de.pengutronix.rauc"
|
||||
DBUS_OBJECT = "/"
|
||||
@ -21,6 +21,8 @@ class Rauc(DBusInterface):
|
||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||
except DBusError:
|
||||
_LOGGER.warning("Can't connect to rauc")
|
||||
except DBusInterfaceError:
|
||||
_LOGGER.warning("Host has no rauc support. OTA updates have been disabled.")
|
||||
|
||||
@dbus_connected
|
||||
def install(self, raucb_file):
|
||||
|
@ -3,10 +3,10 @@ import logging
|
||||
|
||||
from .interface import DBusInterface
|
||||
from .utils import dbus_connected
|
||||
from ..exceptions import DBusError
|
||||
from ..exceptions import DBusError, DBusInterfaceError
|
||||
from ..utils.gdbus import DBus
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
DBUS_NAME = "org.freedesktop.systemd1"
|
||||
DBUS_OBJECT = "/org/freedesktop/systemd1"
|
||||
@ -21,6 +21,10 @@ class Systemd(DBusInterface):
|
||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||
except DBusError:
|
||||
_LOGGER.warning("Can't connect to systemd")
|
||||
except DBusInterfaceError:
|
||||
_LOGGER.warning(
|
||||
"No systemd support on the host. Host control has been disabled."
|
||||
)
|
||||
|
||||
@dbus_connected
|
||||
def reboot(self):
|
||||
|
@ -19,7 +19,7 @@ from .validate import SCHEMA_DISCOVERY_CONFIG, valid_discovery_config
|
||||
if TYPE_CHECKING:
|
||||
from ..addons.addon import Addon
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
CMD_NEW = "post"
|
||||
CMD_DEL = "delete"
|
||||
|
@ -18,7 +18,7 @@ from .misc.forwarder import DNSForward
|
||||
from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_DNS_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
COREDNS_TMPL: Path = Path(__file__).parents[0].joinpath("data/coredns.tmpl")
|
||||
RESOLV_CONF: Path = Path("/etc/resolv.conf")
|
||||
|
@ -11,7 +11,7 @@ from ..const import SOCKET_DOCKER, DNS_SUFFIX
|
||||
from ..exceptions import DockerAPIError
|
||||
from .network import DockerNetwork
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@attr.s(frozen=True)
|
||||
|
@ -32,7 +32,7 @@ if TYPE_CHECKING:
|
||||
from ..addons.addon import Addon
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
AUDIO_DEVICE = "/dev/snd:/dev/snd:rwm"
|
||||
NO_ADDDRESS = ip_address("0.0.0.0")
|
||||
|
@ -7,7 +7,7 @@ from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import DockerAPIError
|
||||
from .interface import DockerInterface
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
DNS_DOCKER_NAME: str = "hassio_dns"
|
||||
|
||||
|
@ -6,7 +6,7 @@ import docker
|
||||
from ..coresys import CoreSysAttributes
|
||||
from .interface import DockerInterface
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DockerHassOSCli(DockerInterface, CoreSysAttributes):
|
||||
|
@ -10,7 +10,7 @@ from ..const import ENV_TIME, ENV_TOKEN, LABEL_MACHINE
|
||||
from ..exceptions import DockerAPIError
|
||||
from .interface import CommandReturn, DockerInterface
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
HASS_DOCKER_NAME = "homeassistant"
|
||||
|
||||
|
@ -13,7 +13,7 @@ from ..exceptions import DockerAPIError
|
||||
from ..utils import process_lock
|
||||
from .stats import DockerStats
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DockerInterface(CoreSysAttributes):
|
||||
|
@ -8,7 +8,7 @@ import docker
|
||||
from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE
|
||||
from ..exceptions import DockerAPIError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DockerNetwork:
|
||||
|
@ -10,7 +10,7 @@ from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import DockerAPIError
|
||||
from .interface import DockerInterface
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
||||
|
@ -149,6 +149,10 @@ class DBusNotConnectedError(HostNotSupportedError):
|
||||
"""DBus is not connected and call a method."""
|
||||
|
||||
|
||||
class DBusInterfaceError(HassioNotSupportedError):
|
||||
"""DBus interface not connected."""
|
||||
|
||||
|
||||
class DBusFatalError(DBusError):
|
||||
"""DBus call going wrong."""
|
||||
|
||||
|
@ -18,7 +18,7 @@ from .exceptions import (
|
||||
DockerAPIError,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HassOS(CoreSysAttributes):
|
||||
|
@ -47,7 +47,7 @@ from .utils import check_port, convert_to_ascii, process_lock
|
||||
from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_HASS_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
RE_YAML_ERROR = re.compile(r"homeassistant\.util\.yaml")
|
||||
|
||||
|
@ -17,7 +17,7 @@ from ..const import (
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import HassioError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HostManager(CoreSysAttributes):
|
||||
|
@ -9,7 +9,7 @@ import attr
|
||||
from ..const import ATTR_INPUT, ATTR_OUTPUT, ATTR_DEVICES, ATTR_NAME, CHAN_ID, CHAN_TYPE
|
||||
from ..coresys import CoreSysAttributes
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
DefaultConfig = attr.make_class("DefaultConfig", ["input", "output"])
|
||||
|
@ -7,7 +7,7 @@ from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import DBusError, HostAppArmorError
|
||||
from ..utils.apparmor import validate_profile
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
SYSTEMD_SERVICES = {"hassos-apparmor.service", "hassio-apparmor.service"}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import HostNotSupportedError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
MANAGER = "manager"
|
||||
HOSTNAME = "hostname"
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import HassioError, HostNotSupportedError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InfoCenter(CoreSysAttributes):
|
||||
|
@ -6,7 +6,7 @@ import attr
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import HassioError, HostNotSupportedError, HostServiceError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
MOD_REPLACE = "replace"
|
||||
|
||||
|
@ -12,7 +12,7 @@ from .utils.dt import utc_from_timestamp, utcnow
|
||||
from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_INGRESS_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Ingress(JsonConfig, CoreSysAttributes):
|
||||
|
@ -7,7 +7,7 @@ from typing import Optional
|
||||
|
||||
import async_timeout
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
COMMAND = "socat UDP-RECVFROM:53,fork UDP-SENDTO:{!s}:53"
|
||||
|
||||
|
@ -9,7 +9,7 @@ import pyudev
|
||||
|
||||
from ..const import ATTR_DEVICES, ATTR_NAME, ATTR_TYPE, CHAN_ID, CHAN_TYPE
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
ASOUND_CARDS: Path = Path("/proc/asound/cards")
|
||||
RE_CARDS: re.Pattern = re.compile(r"(\d+) \[(\w*) *\]: (.*\w)")
|
||||
|
@ -3,7 +3,7 @@ import asyncio
|
||||
from datetime import date, datetime, time, timedelta
|
||||
import logging
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
INTERVAL = "interval"
|
||||
REPEAT = "repeat"
|
||||
|
@ -19,7 +19,7 @@ from ..const import (
|
||||
)
|
||||
from ..interface import ServiceInterface
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# pylint: disable=no-value-for-parameter
|
||||
|
@ -9,7 +9,7 @@ from ..const import FOLDER_HOMEASSISTANT, SNAPSHOT_FULL, SNAPSHOT_PARTIAL
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..utils.dt import utcnow
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SnapshotManager(CoreSysAttributes):
|
||||
|
@ -45,7 +45,7 @@ from ..utils.tar import SecureTarFile
|
||||
from .utils import key_to_iv, password_for_validating, password_to_key, remove_folder
|
||||
from .validate import ALL_FOLDERS, SCHEMA_SNAPSHOT
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Snapshot(CoreSysAttributes):
|
||||
|
@ -9,7 +9,7 @@ from .addon import AddonStore
|
||||
from .data import StoreData
|
||||
from .repository import Repository
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
BUILTIN_REPOSITORIES = set((REPOSITORY_CORE, REPOSITORY_LOCAL))
|
||||
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
from ..coresys import CoreSys
|
||||
from ..addons.model import AddonModel, Data
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddonStore(AddonModel):
|
||||
|
@ -20,7 +20,7 @@ from ..utils.json import read_json_file
|
||||
from .utils import extract_hash_from_path
|
||||
from .validate import SCHEMA_REPOSITORY_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StoreData(CoreSysAttributes):
|
||||
|
@ -12,7 +12,7 @@ from ..const import URL_HASSIO_ADDONS, ATTR_URL, ATTR_BRANCH
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..validate import RE_REPOSITORY
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GitRepo(CoreSysAttributes):
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
import re
|
||||
|
||||
RE_SHA1 = re.compile(r"[a-f0-9]{8}")
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_hash_from_repository(name: str) -> str:
|
||||
|
@ -20,7 +20,7 @@ from .exceptions import (
|
||||
SupervisorUpdateError,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Supervisor(CoreSysAttributes):
|
||||
|
@ -5,7 +5,7 @@ import logging
|
||||
from .coresys import CoreSysAttributes
|
||||
from .exceptions import HomeAssistantError, CoreDNSError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
HASS_WATCHDOG_API = "HASS_WATCHDOG_API"
|
||||
|
||||
|
@ -24,7 +24,7 @@ from .utils import AsyncThrottle
|
||||
from .utils.json import JsonConfig
|
||||
from .validate import SCHEMA_UPDATER_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Updater(JsonConfig, CoreSysAttributes):
|
||||
|
@ -5,7 +5,7 @@ import logging
|
||||
import re
|
||||
import socket
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
RE_STRING = re.compile(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))")
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ import re
|
||||
|
||||
from ..exceptions import AppArmorFileError, AppArmorInvalidError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
RE_PROFILE = re.compile(r"^profile ([^ ]+).*$")
|
||||
|
||||
|
@ -12,7 +12,7 @@ UTC = pytz.utc
|
||||
|
||||
GEOIP_URL = "http://ip-api.com/json/"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Copyright (c) Django Software Foundation and individual contributors.
|
||||
|
@ -1,68 +1,87 @@
|
||||
"""DBus implementation with glib."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import json
|
||||
import shlex
|
||||
import re
|
||||
from signal import SIGINT
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from ..exceptions import DBusFatalError, DBusParseError
|
||||
from ..exceptions import (
|
||||
DBusFatalError,
|
||||
DBusParseError,
|
||||
DBusInterfaceError,
|
||||
DBusNotConnectedError,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
# Use to convert GVariant into json
|
||||
RE_GVARIANT_TYPE = re.compile(
|
||||
RE_GVARIANT_TYPE: re.Match = re.compile(
|
||||
r"(?:boolean|byte|int16|uint16|int32|uint32|handle|int64|uint64|double|"
|
||||
r"string|objectpath|signature) "
|
||||
)
|
||||
RE_GVARIANT_VARIANT = re.compile(
|
||||
RE_GVARIANT_VARIANT: re.Match = re.compile(
|
||||
r"(?<=(?: |{|\[))<((?:'|\").*?(?:'|\")|\d+(?:\.\d+)?)>(?=(?:|]|}|,))"
|
||||
)
|
||||
RE_GVARIANT_STRING = re.compile(r"(?<=(?: |{|\[|\())'(.*?)'(?=(?:|]|}|,|\)))")
|
||||
RE_GVARIANT_TUPLE_O = re.compile(r"\"[^\"]*?\"|(\()")
|
||||
RE_GVARIANT_TUPLE_C = re.compile(r"\"[^\"]*?\"|(,?\))")
|
||||
RE_GVARIANT_STRING_ESC: re.Match = re.compile(
|
||||
r"(?<=(?: |{|\[|\())'[^']*?\"[^']*?'(?=(?:|]|}|,|\)))"
|
||||
)
|
||||
RE_GVARIANT_STRING: re.Match = re.compile(r"(?<=(?: |{|\[|\())'(.*?)'(?=(?:|]|}|,|\)))")
|
||||
RE_GVARIANT_TUPLE_O: re.Match = re.compile(r"\"[^\"\\]*(?:\\.[^\"\\]*)*\"|(\()")
|
||||
RE_GVARIANT_TUPLE_C: re.Match = re.compile(r"\"[^\"\\]*(?:\\.[^\"\\]*)*\"|(,?\))")
|
||||
|
||||
RE_MONITOR_OUTPUT = re.compile(r".+?: (?P<signal>[^ ].+) (?P<data>.*)")
|
||||
RE_MONITOR_OUTPUT: re.Match = re.compile(r".+?: (?P<signal>[^ ].+) (?P<data>.*)")
|
||||
|
||||
# Map GDBus to errors
|
||||
MAP_GDBUS_ERROR: Dict[str, Any] = {
|
||||
"GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown": DBusInterfaceError,
|
||||
"No such file or directory": DBusNotConnectedError,
|
||||
}
|
||||
|
||||
# Commands for dbus
|
||||
INTROSPECT = "gdbus introspect --system --dest {bus} " "--object-path {object} --xml"
|
||||
CALL = (
|
||||
INTROSPECT: str = "gdbus introspect --system --dest {bus} " "--object-path {object} --xml"
|
||||
CALL: str = (
|
||||
"gdbus call --system --dest {bus} --object-path {object} "
|
||||
"--method {method} {args}"
|
||||
)
|
||||
MONITOR = "gdbus monitor --system --dest {bus}"
|
||||
MONITOR: str = "gdbus monitor --system --dest {bus}"
|
||||
|
||||
DBUS_METHOD_GETALL = "org.freedesktop.DBus.Properties.GetAll"
|
||||
DBUS_METHOD_GETALL: str = "org.freedesktop.DBus.Properties.GetAll"
|
||||
|
||||
|
||||
class DBus:
|
||||
"""DBus handler."""
|
||||
|
||||
def __init__(self, bus_name, object_path):
|
||||
def __init__(self, bus_name: str, object_path: str) -> None:
|
||||
"""Initialize dbus object."""
|
||||
self.bus_name = bus_name
|
||||
self.object_path = object_path
|
||||
self.methods = set()
|
||||
self.signals = set()
|
||||
self.bus_name: str = bus_name
|
||||
self.object_path: str = object_path
|
||||
self.methods: Set[str] = set()
|
||||
self.signals: Set[str] = set()
|
||||
|
||||
@staticmethod
|
||||
async def connect(bus_name, object_path):
|
||||
async def connect(bus_name: str, object_path: str) -> DBus:
|
||||
"""Read object data."""
|
||||
self = DBus(bus_name, object_path)
|
||||
await self._init_proxy() # pylint: disable=protected-access
|
||||
|
||||
# pylint: disable=protected-access
|
||||
await self._init_proxy()
|
||||
|
||||
_LOGGER.info("Connect to dbus: %s - %s", bus_name, object_path)
|
||||
return self
|
||||
|
||||
async def _init_proxy(self):
|
||||
async def _init_proxy(self) -> None:
|
||||
"""Read interface data."""
|
||||
command = shlex.split(
|
||||
INTROSPECT.format(bus=self.bus_name, object=self.object_path)
|
||||
)
|
||||
|
||||
# Ask data
|
||||
_LOGGER.info("Introspect %s on %s", self.bus_name, self.object_path)
|
||||
_LOGGER.debug("Introspect %s on %s", self.bus_name, self.object_path)
|
||||
data = await self._send(command)
|
||||
|
||||
# Parse XML
|
||||
@ -73,7 +92,7 @@ class DBus:
|
||||
raise DBusParseError() from None
|
||||
|
||||
# Read available methods
|
||||
_LOGGER.debug("data: %s", data)
|
||||
_LOGGER.debug("Introspect XML: %s", data)
|
||||
for interface in xml.findall("./interface"):
|
||||
interface_name = interface.get("name")
|
||||
|
||||
@ -88,30 +107,34 @@ class DBus:
|
||||
self.signals.add(f"{interface_name}.{signal_name}")
|
||||
|
||||
@staticmethod
|
||||
def parse_gvariant(raw):
|
||||
def parse_gvariant(raw: str) -> Any:
|
||||
"""Parse GVariant input to python."""
|
||||
raw = RE_GVARIANT_TYPE.sub("", raw)
|
||||
raw = RE_GVARIANT_VARIANT.sub(r"\1", raw)
|
||||
raw = RE_GVARIANT_STRING.sub(r'"\1"', raw)
|
||||
raw = RE_GVARIANT_TUPLE_O.sub(
|
||||
lambda x: x.group(0) if not x.group(1) else "[", raw
|
||||
json_raw: str = RE_GVARIANT_TYPE.sub("", raw)
|
||||
json_raw = RE_GVARIANT_VARIANT.sub(r"\1", json_raw)
|
||||
json_raw = RE_GVARIANT_STRING_ESC.sub(
|
||||
lambda x: x.group(0).replace('"', '\\"'), json_raw
|
||||
)
|
||||
raw = RE_GVARIANT_TUPLE_C.sub(
|
||||
lambda x: x.group(0) if not x.group(1) else "]", raw
|
||||
json_raw = RE_GVARIANT_STRING.sub(r'"\1"', json_raw)
|
||||
json_raw = RE_GVARIANT_TUPLE_O.sub(
|
||||
lambda x: x.group(0) if not x.group(1) else "[", json_raw
|
||||
)
|
||||
json_raw = RE_GVARIANT_TUPLE_C.sub(
|
||||
lambda x: x.group(0) if not x.group(1) else "]", json_raw
|
||||
)
|
||||
|
||||
# No data
|
||||
if raw.startswith("[]"):
|
||||
if json_raw.startswith("[]"):
|
||||
return []
|
||||
|
||||
try:
|
||||
return json.loads(raw)
|
||||
return json.loads(json_raw)
|
||||
except json.JSONDecodeError as err:
|
||||
_LOGGER.error("Can't parse '%s': %s", raw, err)
|
||||
_LOGGER.error("Can't parse '%s': %s", json_raw, err)
|
||||
_LOGGER.debug("GVariant data: '%s'", raw)
|
||||
raise DBusParseError() from None
|
||||
|
||||
@staticmethod
|
||||
def gvariant_args(args):
|
||||
def gvariant_args(args: List[Any]) -> str:
|
||||
"""Convert args into gvariant."""
|
||||
gvariant = ""
|
||||
for arg in args:
|
||||
@ -122,11 +145,11 @@ class DBus:
|
||||
elif isinstance(arg, str):
|
||||
gvariant += f' "{arg}"'
|
||||
else:
|
||||
gvariant += " {}".format(str(arg))
|
||||
gvariant += f" {arg!s}"
|
||||
|
||||
return gvariant.lstrip()
|
||||
|
||||
async def call_dbus(self, method, *args):
|
||||
async def call_dbus(self, method: str, *args: List[Any]) -> str:
|
||||
"""Call a dbus method."""
|
||||
command = shlex.split(
|
||||
CALL.format(
|
||||
@ -142,10 +165,9 @@ class DBus:
|
||||
data = await self._send(command)
|
||||
|
||||
# Parse and return data
|
||||
_LOGGER.debug("Receive from %s: %s", method, data)
|
||||
return self.parse_gvariant(data)
|
||||
|
||||
async def get_properties(self, interface):
|
||||
async def get_properties(self, interface: str) -> Dict[str, Any]:
|
||||
"""Read all properties from interface."""
|
||||
try:
|
||||
return (await self.call_dbus(DBUS_METHOD_GETALL, interface))[0]
|
||||
@ -153,7 +175,7 @@ class DBus:
|
||||
_LOGGER.error("No attributes returned for %s", interface)
|
||||
raise DBusFatalError from None
|
||||
|
||||
async def _send(self, command):
|
||||
async def _send(self, command: List[str]) -> str:
|
||||
"""Send command over dbus."""
|
||||
# Run command
|
||||
_LOGGER.debug("Send dbus command: %s", command)
|
||||
@ -171,13 +193,20 @@ class DBus:
|
||||
raise DBusFatalError() from None
|
||||
|
||||
# Success?
|
||||
if proc.returncode != 0:
|
||||
if proc.returncode == 0:
|
||||
return data.decode()
|
||||
|
||||
# Filter error
|
||||
error = error.decode()
|
||||
for msg, exception in MAP_GDBUS_ERROR.items():
|
||||
if msg not in error:
|
||||
continue
|
||||
raise exception()
|
||||
|
||||
# General
|
||||
_LOGGER.error("DBus return error: %s", error)
|
||||
raise DBusFatalError()
|
||||
|
||||
# End
|
||||
return data.decode()
|
||||
|
||||
def attach_signals(self, filters=None):
|
||||
"""Generate a signals wrapper."""
|
||||
return DBusSignalWrapper(self, filters)
|
||||
@ -189,7 +218,7 @@ class DBus:
|
||||
async for signal in signals:
|
||||
return signal
|
||||
|
||||
def __getattr__(self, name):
|
||||
def __getattr__(self, name: str) -> DBusCallWrapper:
|
||||
"""Mapping to dbus method."""
|
||||
return getattr(DBusCallWrapper(self, self.bus_name), name)
|
||||
|
||||
@ -197,17 +226,17 @@ class DBus:
|
||||
class DBusCallWrapper:
|
||||
"""Wrapper a DBus interface for a call."""
|
||||
|
||||
def __init__(self, dbus, interface):
|
||||
def __init__(self, dbus: DBus, interface: str) -> None:
|
||||
"""Initialize wrapper."""
|
||||
self.dbus = dbus
|
||||
self.interface = interface
|
||||
self.dbus: DBus = dbus
|
||||
self.interface: str = interface
|
||||
|
||||
def __call__(self):
|
||||
def __call__(self) -> None:
|
||||
"""Should never be called."""
|
||||
_LOGGER.error("DBus method %s not exists!", self.interface)
|
||||
raise DBusFatalError()
|
||||
|
||||
def __getattr__(self, name):
|
||||
def __getattr__(self, name: str):
|
||||
"""Mapping to dbus method."""
|
||||
interface = f"{self.interface}.{name}"
|
||||
|
||||
@ -227,11 +256,11 @@ class DBusCallWrapper:
|
||||
class DBusSignalWrapper:
|
||||
"""Process Signals."""
|
||||
|
||||
def __init__(self, dbus, signals=None):
|
||||
def __init__(self, dbus: DBus, signals: Optional[str] = None):
|
||||
"""Initialize dbus signal wrapper."""
|
||||
self.dbus = dbus
|
||||
self._signals = signals
|
||||
self._proc = None
|
||||
self.dbus: DBus = dbus
|
||||
self._signals: Optional[str] = signals
|
||||
self._proc: Optional[asyncio.Process] = None
|
||||
|
||||
async def __aenter__(self):
|
||||
"""Start monitor events."""
|
||||
|
@ -9,7 +9,7 @@ from voluptuous.humanize import humanize_error
|
||||
|
||||
from ..exceptions import JsonFileError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def write_json_file(jsonfile: Path, data: Any) -> None:
|
||||
|
278
tests/utils/test_gvariant_parser.py
Normal file
278
tests/utils/test_gvariant_parser.py
Normal file
@ -0,0 +1,278 @@
|
||||
"""Test gdbus gvariant parser."""
|
||||
from hassio.utils.gdbus import DBus
|
||||
|
||||
|
||||
def test_simple_return():
|
||||
"""Test Simple return value."""
|
||||
raw = "(objectpath '/org/freedesktop/systemd1/job/35383',)"
|
||||
|
||||
# parse data
|
||||
data = DBus.parse_gvariant(raw)
|
||||
|
||||
assert data == ["/org/freedesktop/systemd1/job/35383"]
|
||||
|
||||
|
||||
def test_get_property():
|
||||
"""Test Property parsing."""
|
||||
raw = "({'Hostname': <'hassio'>, 'StaticHostname': <'hassio'>, 'PrettyHostname': <''>, 'IconName': <'computer-embedded'>, 'Chassis': <'embedded'>, 'Deployment': <'production'>, 'Location': <''>, 'KernelName': <'Linux'>, 'KernelRelease': <'4.14.98-v7'>, 'KernelVersion': <'#1 SMP Sat May 11 02:17:06 UTC 2019'>, 'OperatingSystemPrettyName': <'HassOS 2.12'>, 'OperatingSystemCPEName': <'cpe:2.3:o:home_assistant:hassos:2.12:*:production:*:*:*:rpi3:*'>, 'HomeURL': <'https://hass.io/'>},)"
|
||||
|
||||
# parse data
|
||||
data = DBus.parse_gvariant(raw)
|
||||
|
||||
assert data[0] == {
|
||||
"Hostname": "hassio",
|
||||
"StaticHostname": "hassio",
|
||||
"PrettyHostname": "",
|
||||
"IconName": "computer-embedded",
|
||||
"Chassis": "embedded",
|
||||
"Deployment": "production",
|
||||
"Location": "",
|
||||
"KernelName": "Linux",
|
||||
"KernelRelease": "4.14.98-v7",
|
||||
"KernelVersion": "#1 SMP Sat May 11 02:17:06 UTC 2019",
|
||||
"OperatingSystemPrettyName": "HassOS 2.12",
|
||||
"OperatingSystemCPEName": "cpe:2.3:o:home_assistant:hassos:2.12:*:production:*:*:*:rpi3:*",
|
||||
"HomeURL": "https://hass.io/",
|
||||
}
|
||||
|
||||
|
||||
def test_systemd_unitlist_simple():
|
||||
"""Test Systemd Unit list simple."""
|
||||
raw = "([('systemd-remount-fs.service', 'Remount Root and Kernel File Systems', 'loaded', 'active', 'exited', '', objectpath '/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice', uint32 0, '', objectpath '/'), ('sys-subsystem-net-devices-veth5714b4e.device', '/sys/subsystem/net/devices/veth5714b4e', 'loaded', 'active', 'plugged', '', '/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dveth5714b4e_2edevice', 0, '', '/'), ('rauc.service', 'Rauc Update Service', 'loaded', 'active', 'running', '', '/org/freedesktop/systemd1/unit/rauc_2eservice', 0, '', '/'), ('mnt-data-docker-overlay2-7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2-merged.mount', '/mnt/data/docker/overlay2/7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2/merged', 'loaded', 'active', 'mounted', '', '/org/freedesktop/systemd1/unit/mnt_2ddata_2ddocker_2doverlay2_2d7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2_2dmerged_2emount', 0, '', '/'), ('hassos-hardware.target', 'HassOS hardware targets', 'loaded', 'active', 'active', '', '/org/freedesktop/systemd1/unit/hassos_2dhardware_2etarget', 0, '', '/'), ('dev-zram1.device', '/dev/zram1', 'loaded', 'active', 'plugged', 'sys-devices-virtual-block-zram1.device', '/org/freedesktop/systemd1/unit/dev_2dzram1_2edevice', 0, '', '/'), ('sys-subsystem-net-devices-hassio.device', '/sys/subsystem/net/devices/hassio', 'loaded', 'active', 'plugged', '', '/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dhassio_2edevice', 0, '', '/'), ('cryptsetup.target', 'cryptsetup.target', 'not-found', 'inactive', 'dead', '', '/org/freedesktop/systemd1/unit/cryptsetup_2etarget', 0, '', '/'), ('sys-devices-virtual-net-vethd256dfa.device', '/sys/devices/virtual/net/vethd256dfa', 'loaded', 'active', 'plugged', '', '/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dnet_2dvethd256dfa_2edevice', 0, '', '/'), ('network-pre.target', 'Network (Pre)', 'loaded', 'inactive', 'dead', '', '/org/freedesktop/systemd1/unit/network_2dpre_2etarget', 0, '', '/'), ('sys-devices-virtual-net-veth5714b4e.device', '/sys/devices/virtual/net/veth5714b4e', 'loaded', 'active', 'plugged', '', '/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dnet_2dveth5714b4e_2edevice', 0, '', '/'), ('sys-kernel-debug.mount', 'Kernel Debug File System', 'loaded', 'active', 'mounted', '', '/org/freedesktop/systemd1/unit/sys_2dkernel_2ddebug_2emount', 0, '', '/'), ('slices.target', 'Slices', 'loaded', 'active', 'active', '', '/org/freedesktop/systemd1/unit/slices_2etarget', 0, '', '/'), ('etc-NetworkManager-system\x2dconnections.mount', 'NetworkManager persistent system connections', 'loaded', 'active', 'mounted', '', '/org/freedesktop/systemd1/unit/etc_2dNetworkManager_2dsystem_5cx2dconnections_2emount', 0, '', '/'), ('run-docker-netns-26ede3178729.mount', '/run/docker/netns/26ede3178729', 'loaded', 'active', 'mounted', '', '/org/freedesktop/systemd1/unit/run_2ddocker_2dnetns_2d26ede3178729_2emount', 0, '', '/'), ('dev-disk-by\x2dpath-platform\x2d3f202000.mmc\x2dpart2.device', '/dev/disk/by-path/platform-3f202000.mmc-part2', 'loaded', 'active', 'plugged', 'sys-devices-platform-soc-3f202000.mmc-mmc_host-mmc0-mmc0:e624-block-mmcblk0-mmcblk0p2.device', '/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dplatform_5cx2d3f202000_2emmc_5cx2dpart2_2edevice', 0, '', '/')],)"
|
||||
|
||||
# parse data
|
||||
data = DBus.parse_gvariant(raw)
|
||||
|
||||
assert data == [
|
||||
[
|
||||
[
|
||||
"systemd-remount-fs.service",
|
||||
"Remount Root and Kernel File Systems",
|
||||
"loaded",
|
||||
"active",
|
||||
"exited",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-subsystem-net-devices-veth5714b4e.device",
|
||||
"/sys/subsystem/net/devices/veth5714b4e",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dveth5714b4e_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"rauc.service",
|
||||
"Rauc Update Service",
|
||||
"loaded",
|
||||
"active",
|
||||
"running",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/rauc_2eservice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"mnt-data-docker-overlay2-7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2-merged.mount",
|
||||
"/mnt/data/docker/overlay2/7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2/merged",
|
||||
"loaded",
|
||||
"active",
|
||||
"mounted",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/mnt_2ddata_2ddocker_2doverlay2_2d7493c48dd99ab0e68420e3317d93711630dd55a76d4f2a21863a220031203ac2_2dmerged_2emount",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"hassos-hardware.target",
|
||||
"HassOS hardware targets",
|
||||
"loaded",
|
||||
"active",
|
||||
"active",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/hassos_2dhardware_2etarget",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"dev-zram1.device",
|
||||
"/dev/zram1",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"sys-devices-virtual-block-zram1.device",
|
||||
"/org/freedesktop/systemd1/unit/dev_2dzram1_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-subsystem-net-devices-hassio.device",
|
||||
"/sys/subsystem/net/devices/hassio",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dhassio_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"cryptsetup.target",
|
||||
"cryptsetup.target",
|
||||
"not-found",
|
||||
"inactive",
|
||||
"dead",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/cryptsetup_2etarget",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-devices-virtual-net-vethd256dfa.device",
|
||||
"/sys/devices/virtual/net/vethd256dfa",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dnet_2dvethd256dfa_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"network-pre.target",
|
||||
"Network (Pre)",
|
||||
"loaded",
|
||||
"inactive",
|
||||
"dead",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/network_2dpre_2etarget",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-devices-virtual-net-veth5714b4e.device",
|
||||
"/sys/devices/virtual/net/veth5714b4e",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dnet_2dveth5714b4e_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-kernel-debug.mount",
|
||||
"Kernel Debug File System",
|
||||
"loaded",
|
||||
"active",
|
||||
"mounted",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2dkernel_2ddebug_2emount",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"slices.target",
|
||||
"Slices",
|
||||
"loaded",
|
||||
"active",
|
||||
"active",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/slices_2etarget",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"etc-NetworkManager-system-connections.mount",
|
||||
"NetworkManager persistent system connections",
|
||||
"loaded",
|
||||
"active",
|
||||
"mounted",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/etc_2dNetworkManager_2dsystem_5cx2dconnections_2emount",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"run-docker-netns-26ede3178729.mount",
|
||||
"/run/docker/netns/26ede3178729",
|
||||
"loaded",
|
||||
"active",
|
||||
"mounted",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/run_2ddocker_2dnetns_2d26ede3178729_2emount",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"dev-disk-by-path-platform-3f202000.mmc-part2.device",
|
||||
"/dev/disk/by-path/platform-3f202000.mmc-part2",
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"sys-devices-platform-soc-3f202000.mmc-mmc_host-mmc0-mmc0:e624-block-mmcblk0-mmcblk0p2.device",
|
||||
"/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dplatform_5cx2d3f202000_2emmc_5cx2dpart2_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
def test_systemd_unitlist_complex():
|
||||
"""Test Systemd Unit list simple."""
|
||||
raw = "([('systemd-remount-fs.service', 'Remount Root and \"Kernel File Systems\"', 'loaded', 'active', 'exited', '', objectpath '/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice', uint32 0, '', objectpath '/'), ('sys-subsystem-net-devices-veth5714b4e.device', '/sys/subsystem/net/devices/veth5714b4e for \" is', 'loaded', 'active', 'plugged', '', '/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dveth5714b4e_2edevice', 0, '', '/')],)"
|
||||
|
||||
# parse data
|
||||
data = DBus.parse_gvariant(raw)
|
||||
|
||||
assert data == [
|
||||
[
|
||||
[
|
||||
"systemd-remount-fs.service",
|
||||
'Remount Root and "Kernel File Systems"',
|
||||
"loaded",
|
||||
"active",
|
||||
"exited",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
[
|
||||
"sys-subsystem-net-devices-veth5714b4e.device",
|
||||
'/sys/subsystem/net/devices/veth5714b4e for " is',
|
||||
"loaded",
|
||||
"active",
|
||||
"plugged",
|
||||
"",
|
||||
"/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dveth5714b4e_2edevice",
|
||||
0,
|
||||
"",
|
||||
"/",
|
||||
],
|
||||
]
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user