mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-06-22 18:06: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
|
from hassio import bootstrap
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def initialize_event_loop():
|
def initialize_event_loop():
|
||||||
|
@ -19,7 +19,7 @@ from ..store.addon import AddonStore
|
|||||||
from .addon import Addon
|
from .addon import Addon
|
||||||
from .data import AddonsData
|
from .data import AddonsData
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
AnyAddon = Union[Addon, AddonStore]
|
AnyAddon = Union[Addon, AddonStore]
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ from .model import AddonModel, Data
|
|||||||
from .utils import remove_data
|
from .utils import remove_data
|
||||||
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
|
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
RE_WEBUI = re.compile(
|
RE_WEBUI = re.compile(
|
||||||
r"^(?:(?P<s_prefix>https?)|\[PROTO:(?P<t_proto>\w+)\])"
|
r"^(?:(?P<s_prefix>https?)|\[PROTO:(?P<t_proto>\w+)\])"
|
||||||
|
@ -17,7 +17,7 @@ from ..store.addon import AddonStore
|
|||||||
from .addon import Addon
|
from .addon import Addon
|
||||||
from .validate import SCHEMA_ADDONS_FILE
|
from .validate import SCHEMA_ADDONS_FILE
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
Config = Dict[str, Any]
|
Config = Dict[str, Any]
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ from ..const import (
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .model import AddonModel
|
from .model import AddonModel
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def rating_security(addon: AddonModel) -> int:
|
def rating_security(addon: AddonModel) -> int:
|
||||||
|
@ -95,7 +95,7 @@ from ..validate import (
|
|||||||
UUID_MATCH,
|
UUID_MATCH,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
RE_VOLUME = re.compile(r"^(config|ssl|addons|backup|share)(?::(rw|ro))?$")
|
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 .snapshots import APISnapshots
|
||||||
from .supervisor import APISupervisor
|
from .supervisor import APISupervisor
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RestAPI(CoreSysAttributes):
|
class RestAPI(CoreSysAttributes):
|
||||||
|
@ -94,7 +94,7 @@ from ..exceptions import APIError
|
|||||||
from ..validate import ALSA_DEVICE, DOCKER_PORTS
|
from ..validate import ALSA_DEVICE, DOCKER_PORTS
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
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)})
|
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 ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIForbidden
|
from ..exceptions import APIForbidden
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class APIAuth(CoreSysAttributes):
|
class APIAuth(CoreSysAttributes):
|
||||||
|
@ -26,7 +26,7 @@ from ..exceptions import APIError
|
|||||||
from ..validate import DNS_SERVER_LIST
|
from ..validate import DNS_SERVER_LIST
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
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
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_SERVERS): DNS_SERVER_LIST})
|
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_SERVERS): DNS_SERVER_LIST})
|
||||||
|
@ -12,7 +12,7 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class APIHardware(CoreSysAttributes):
|
class APIHardware(CoreSysAttributes):
|
||||||
|
@ -16,7 +16,7 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from .utils import api_process, api_validate
|
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)})
|
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 ..validate import DOCKER_IMAGE, NETWORK_PORT
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
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
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_OPTIONS = vol.Schema(
|
SCHEMA_OPTIONS = vol.Schema(
|
||||||
|
@ -20,7 +20,7 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
SERVICE = "service"
|
SERVICE = "service"
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from .utils import api_process
|
from .utils import api_process
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class APIInfo(CoreSysAttributes):
|
class APIInfo(CoreSysAttributes):
|
||||||
|
@ -28,7 +28,7 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from .utils import api_process
|
from .utils import api_process
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class APIIngress(CoreSysAttributes):
|
class APIIngress(CoreSysAttributes):
|
||||||
|
@ -14,7 +14,7 @@ from ..const import HEADER_HA_ACCESS
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
|
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class APIProxy(CoreSysAttributes):
|
class APIProxy(CoreSysAttributes):
|
||||||
|
@ -16,7 +16,7 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# 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 ..validate import CHANNELS, LOG_LEVEL, REPOSITORIES, WAIT_BOOT
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
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
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_OPTIONS = vol.Schema(
|
SCHEMA_OPTIONS = vol.Schema(
|
||||||
|
@ -16,7 +16,7 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..exceptions import HassioError, APIError, APIForbidden
|
from ..exceptions import HassioError, APIError, APIForbidden
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def json_loads(data):
|
def json_loads(data):
|
||||||
|
@ -8,7 +8,7 @@ from .coresys import CoreSys, CoreSysAttributes
|
|||||||
from .exceptions import HassioArchNotFound, JsonFileError
|
from .exceptions import HassioArchNotFound, JsonFileError
|
||||||
from .utils.json import read_json_file
|
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")
|
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 .validate import SCHEMA_AUTH_CONFIG
|
||||||
from .exceptions import AuthError, HomeAssistantAPIError
|
from .exceptions import AuthError, HomeAssistantAPIError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Auth(JsonConfig, CoreSysAttributes):
|
class Auth(JsonConfig, CoreSysAttributes):
|
||||||
|
@ -29,7 +29,7 @@ from .tasks import Tasks
|
|||||||
from .updater import Updater
|
from .updater import Updater
|
||||||
from .utils.dt import fetch_timezone
|
from .utils.dt import fetch_timezone
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
ENV_SHARE = "SUPERVISOR_SHARE"
|
ENV_SHARE = "SUPERVISOR_SHARE"
|
||||||
ENV_NAME = "SUPERVISOR_NAME"
|
ENV_NAME = "SUPERVISOR_NAME"
|
||||||
|
@ -19,7 +19,7 @@ from .utils.dt import parse_datetime
|
|||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_HASSIO_CONFIG
|
from .validate import SCHEMA_HASSIO_CONFIG
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
HOMEASSISTANT_CONFIG = PurePath("homeassistant")
|
HOMEASSISTANT_CONFIG = PurePath("homeassistant")
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ from .const import (
|
|||||||
)
|
)
|
||||||
from .exceptions import HassioError, HomeAssistantError, SupervisorUpdateError
|
from .exceptions import HassioError, HomeAssistantError, SupervisorUpdateError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HassIO(CoreSysAttributes):
|
class HassIO(CoreSysAttributes):
|
||||||
|
@ -1,39 +1,49 @@
|
|||||||
"""D-Bus interface objects."""
|
"""D-Bus interface objects."""
|
||||||
|
import logging
|
||||||
|
|
||||||
from .systemd import Systemd
|
from .systemd import Systemd
|
||||||
from .hostname import Hostname
|
from .hostname import Hostname
|
||||||
from .rauc import Rauc
|
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):
|
class DBusManager(CoreSysAttributes):
|
||||||
"""A DBus Interface handler."""
|
"""A DBus Interface handler."""
|
||||||
|
|
||||||
def __init__(self, coresys):
|
def __init__(self, coresys: CoreSys) -> None:
|
||||||
"""Initialize D-Bus interface."""
|
"""Initialize D-Bus interface."""
|
||||||
self.coresys = coresys
|
self.coresys: CoreSys = coresys
|
||||||
|
|
||||||
self._systemd = Systemd()
|
self._systemd: Systemd = Systemd()
|
||||||
self._hostname = Hostname()
|
self._hostname: Hostname = Hostname()
|
||||||
self._rauc = Rauc()
|
self._rauc: Rauc = Rauc()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def systemd(self):
|
def systemd(self) -> Systemd:
|
||||||
"""Return the systemd interface."""
|
"""Return the systemd interface."""
|
||||||
return self._systemd
|
return self._systemd
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hostname(self):
|
def hostname(self) -> Hostname:
|
||||||
"""Return the hostname interface."""
|
"""Return the hostname interface."""
|
||||||
return self._hostname
|
return self._hostname
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rauc(self):
|
def rauc(self) -> Rauc:
|
||||||
"""Return the rauc interface."""
|
"""Return the rauc interface."""
|
||||||
return self._rauc
|
return self._rauc
|
||||||
|
|
||||||
async def load(self):
|
async def load(self) -> None:
|
||||||
"""Connect interfaces to D-Bus."""
|
"""Connect interfaces to D-Bus."""
|
||||||
await self.systemd.connect()
|
|
||||||
await self.hostname.connect()
|
try:
|
||||||
await self.rauc.connect()
|
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 .interface import DBusInterface
|
||||||
from .utils import dbus_connected
|
from .utils import dbus_connected
|
||||||
from ..exceptions import DBusError
|
from ..exceptions import DBusError, DBusInterfaceError
|
||||||
from ..utils.gdbus import DBus
|
from ..utils.gdbus import DBus
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DBUS_NAME = "org.freedesktop.hostname1"
|
DBUS_NAME = "org.freedesktop.hostname1"
|
||||||
DBUS_OBJECT = "/org/freedesktop/hostname1"
|
DBUS_OBJECT = "/org/freedesktop/hostname1"
|
||||||
@ -21,6 +21,10 @@ class Hostname(DBusInterface):
|
|||||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||||
except DBusError:
|
except DBusError:
|
||||||
_LOGGER.warning("Can't connect to hostname")
|
_LOGGER.warning("Can't connect to hostname")
|
||||||
|
except DBusInterfaceError:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"No hostname support on the host. Hostname functions have been disabled."
|
||||||
|
)
|
||||||
|
|
||||||
@dbus_connected
|
@dbus_connected
|
||||||
def set_static_hostname(self, hostname):
|
def set_static_hostname(self, hostname):
|
||||||
|
@ -3,10 +3,10 @@ import logging
|
|||||||
|
|
||||||
from .interface import DBusInterface
|
from .interface import DBusInterface
|
||||||
from .utils import dbus_connected
|
from .utils import dbus_connected
|
||||||
from ..exceptions import DBusError
|
from ..exceptions import DBusError, DBusInterfaceError
|
||||||
from ..utils.gdbus import DBus
|
from ..utils.gdbus import DBus
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DBUS_NAME = "de.pengutronix.rauc"
|
DBUS_NAME = "de.pengutronix.rauc"
|
||||||
DBUS_OBJECT = "/"
|
DBUS_OBJECT = "/"
|
||||||
@ -21,6 +21,8 @@ class Rauc(DBusInterface):
|
|||||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||||
except DBusError:
|
except DBusError:
|
||||||
_LOGGER.warning("Can't connect to rauc")
|
_LOGGER.warning("Can't connect to rauc")
|
||||||
|
except DBusInterfaceError:
|
||||||
|
_LOGGER.warning("Host has no rauc support. OTA updates have been disabled.")
|
||||||
|
|
||||||
@dbus_connected
|
@dbus_connected
|
||||||
def install(self, raucb_file):
|
def install(self, raucb_file):
|
||||||
|
@ -3,10 +3,10 @@ import logging
|
|||||||
|
|
||||||
from .interface import DBusInterface
|
from .interface import DBusInterface
|
||||||
from .utils import dbus_connected
|
from .utils import dbus_connected
|
||||||
from ..exceptions import DBusError
|
from ..exceptions import DBusError, DBusInterfaceError
|
||||||
from ..utils.gdbus import DBus
|
from ..utils.gdbus import DBus
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DBUS_NAME = "org.freedesktop.systemd1"
|
DBUS_NAME = "org.freedesktop.systemd1"
|
||||||
DBUS_OBJECT = "/org/freedesktop/systemd1"
|
DBUS_OBJECT = "/org/freedesktop/systemd1"
|
||||||
@ -21,6 +21,10 @@ class Systemd(DBusInterface):
|
|||||||
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
self.dbus = await DBus.connect(DBUS_NAME, DBUS_OBJECT)
|
||||||
except DBusError:
|
except DBusError:
|
||||||
_LOGGER.warning("Can't connect to systemd")
|
_LOGGER.warning("Can't connect to systemd")
|
||||||
|
except DBusInterfaceError:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"No systemd support on the host. Host control has been disabled."
|
||||||
|
)
|
||||||
|
|
||||||
@dbus_connected
|
@dbus_connected
|
||||||
def reboot(self):
|
def reboot(self):
|
||||||
|
@ -19,7 +19,7 @@ from .validate import SCHEMA_DISCOVERY_CONFIG, valid_discovery_config
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..addons.addon import Addon
|
from ..addons.addon import Addon
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
CMD_NEW = "post"
|
CMD_NEW = "post"
|
||||||
CMD_DEL = "delete"
|
CMD_DEL = "delete"
|
||||||
|
@ -18,7 +18,7 @@ from .misc.forwarder import DNSForward
|
|||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_DNS_CONFIG
|
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")
|
COREDNS_TMPL: Path = Path(__file__).parents[0].joinpath("data/coredns.tmpl")
|
||||||
RESOLV_CONF: Path = Path("/etc/resolv.conf")
|
RESOLV_CONF: Path = Path("/etc/resolv.conf")
|
||||||
|
@ -11,7 +11,7 @@ from ..const import SOCKET_DOCKER, DNS_SUFFIX
|
|||||||
from ..exceptions import DockerAPIError
|
from ..exceptions import DockerAPIError
|
||||||
from .network import DockerNetwork
|
from .network import DockerNetwork
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True)
|
||||||
|
@ -32,7 +32,7 @@ if TYPE_CHECKING:
|
|||||||
from ..addons.addon import Addon
|
from ..addons.addon import Addon
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
AUDIO_DEVICE = "/dev/snd:/dev/snd:rwm"
|
AUDIO_DEVICE = "/dev/snd:/dev/snd:rwm"
|
||||||
NO_ADDDRESS = ip_address("0.0.0.0")
|
NO_ADDDRESS = ip_address("0.0.0.0")
|
||||||
|
@ -7,7 +7,7 @@ from ..coresys import CoreSysAttributes
|
|||||||
from ..exceptions import DockerAPIError
|
from ..exceptions import DockerAPIError
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DNS_DOCKER_NAME: str = "hassio_dns"
|
DNS_DOCKER_NAME: str = "hassio_dns"
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import docker
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DockerHassOSCli(DockerInterface, CoreSysAttributes):
|
class DockerHassOSCli(DockerInterface, CoreSysAttributes):
|
||||||
|
@ -10,7 +10,7 @@ from ..const import ENV_TIME, ENV_TOKEN, LABEL_MACHINE
|
|||||||
from ..exceptions import DockerAPIError
|
from ..exceptions import DockerAPIError
|
||||||
from .interface import CommandReturn, DockerInterface
|
from .interface import CommandReturn, DockerInterface
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
HASS_DOCKER_NAME = "homeassistant"
|
HASS_DOCKER_NAME = "homeassistant"
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from ..exceptions import DockerAPIError
|
|||||||
from ..utils import process_lock
|
from ..utils import process_lock
|
||||||
from .stats import DockerStats
|
from .stats import DockerStats
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DockerInterface(CoreSysAttributes):
|
class DockerInterface(CoreSysAttributes):
|
||||||
|
@ -8,7 +8,7 @@ import docker
|
|||||||
from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE
|
from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE
|
||||||
from ..exceptions import DockerAPIError
|
from ..exceptions import DockerAPIError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DockerNetwork:
|
class DockerNetwork:
|
||||||
|
@ -10,7 +10,7 @@ from ..coresys import CoreSysAttributes
|
|||||||
from ..exceptions import DockerAPIError
|
from ..exceptions import DockerAPIError
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
class DockerSupervisor(DockerInterface, CoreSysAttributes):
|
||||||
|
@ -149,6 +149,10 @@ class DBusNotConnectedError(HostNotSupportedError):
|
|||||||
"""DBus is not connected and call a method."""
|
"""DBus is not connected and call a method."""
|
||||||
|
|
||||||
|
|
||||||
|
class DBusInterfaceError(HassioNotSupportedError):
|
||||||
|
"""DBus interface not connected."""
|
||||||
|
|
||||||
|
|
||||||
class DBusFatalError(DBusError):
|
class DBusFatalError(DBusError):
|
||||||
"""DBus call going wrong."""
|
"""DBus call going wrong."""
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ from .exceptions import (
|
|||||||
DockerAPIError,
|
DockerAPIError,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HassOS(CoreSysAttributes):
|
class HassOS(CoreSysAttributes):
|
||||||
|
@ -47,7 +47,7 @@ from .utils import check_port, convert_to_ascii, process_lock
|
|||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_HASS_CONFIG
|
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")
|
RE_YAML_ERROR = re.compile(r"homeassistant\.util\.yaml")
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from ..const import (
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HassioError
|
from ..exceptions import HassioError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HostManager(CoreSysAttributes):
|
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 ..const import ATTR_INPUT, ATTR_OUTPUT, ATTR_DEVICES, ATTR_NAME, CHAN_ID, CHAN_TYPE
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
DefaultConfig = attr.make_class("DefaultConfig", ["input", "output"])
|
DefaultConfig = attr.make_class("DefaultConfig", ["input", "output"])
|
||||||
|
@ -7,7 +7,7 @@ from ..coresys import CoreSysAttributes
|
|||||||
from ..exceptions import DBusError, HostAppArmorError
|
from ..exceptions import DBusError, HostAppArmorError
|
||||||
from ..utils.apparmor import validate_profile
|
from ..utils.apparmor import validate_profile
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
SYSTEMD_SERVICES = {"hassos-apparmor.service", "hassio-apparmor.service"}
|
SYSTEMD_SERVICES = {"hassos-apparmor.service", "hassio-apparmor.service"}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import logging
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HostNotSupportedError
|
from ..exceptions import HostNotSupportedError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
MANAGER = "manager"
|
MANAGER = "manager"
|
||||||
HOSTNAME = "hostname"
|
HOSTNAME = "hostname"
|
||||||
|
@ -4,7 +4,7 @@ import logging
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HassioError, HostNotSupportedError
|
from ..exceptions import HassioError, HostNotSupportedError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class InfoCenter(CoreSysAttributes):
|
class InfoCenter(CoreSysAttributes):
|
||||||
|
@ -6,7 +6,7 @@ import attr
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HassioError, HostNotSupportedError, HostServiceError
|
from ..exceptions import HassioError, HostNotSupportedError, HostServiceError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
MOD_REPLACE = "replace"
|
MOD_REPLACE = "replace"
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ from .utils.dt import utc_from_timestamp, utcnow
|
|||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_INGRESS_CONFIG
|
from .validate import SCHEMA_INGRESS_CONFIG
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Ingress(JsonConfig, CoreSysAttributes):
|
class Ingress(JsonConfig, CoreSysAttributes):
|
||||||
|
@ -7,7 +7,7 @@ from typing import Optional
|
|||||||
|
|
||||||
import async_timeout
|
import async_timeout
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
COMMAND = "socat UDP-RECVFROM:53,fork UDP-SENDTO:{!s}:53"
|
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
|
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")
|
ASOUND_CARDS: Path = Path("/proc/asound/cards")
|
||||||
RE_CARDS: re.Pattern = re.compile(r"(\d+) \[(\w*) *\]: (.*\w)")
|
RE_CARDS: re.Pattern = re.compile(r"(\d+) \[(\w*) *\]: (.*\w)")
|
||||||
|
@ -3,7 +3,7 @@ import asyncio
|
|||||||
from datetime import date, datetime, time, timedelta
|
from datetime import date, datetime, time, timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
INTERVAL = "interval"
|
INTERVAL = "interval"
|
||||||
REPEAT = "repeat"
|
REPEAT = "repeat"
|
||||||
|
@ -19,7 +19,7 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..interface import ServiceInterface
|
from ..interface import ServiceInterface
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
|
@ -9,7 +9,7 @@ from ..const import FOLDER_HOMEASSISTANT, SNAPSHOT_FULL, SNAPSHOT_PARTIAL
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..utils.dt import utcnow
|
from ..utils.dt import utcnow
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SnapshotManager(CoreSysAttributes):
|
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 .utils import key_to_iv, password_for_validating, password_to_key, remove_folder
|
||||||
from .validate import ALL_FOLDERS, SCHEMA_SNAPSHOT
|
from .validate import ALL_FOLDERS, SCHEMA_SNAPSHOT
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Snapshot(CoreSysAttributes):
|
class Snapshot(CoreSysAttributes):
|
||||||
|
@ -9,7 +9,7 @@ from .addon import AddonStore
|
|||||||
from .data import StoreData
|
from .data import StoreData
|
||||||
from .repository import Repository
|
from .repository import Repository
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
BUILTIN_REPOSITORIES = set((REPOSITORY_CORE, REPOSITORY_LOCAL))
|
BUILTIN_REPOSITORIES = set((REPOSITORY_CORE, REPOSITORY_LOCAL))
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import logging
|
|||||||
from ..coresys import CoreSys
|
from ..coresys import CoreSys
|
||||||
from ..addons.model import AddonModel, Data
|
from ..addons.model import AddonModel, Data
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AddonStore(AddonModel):
|
class AddonStore(AddonModel):
|
||||||
|
@ -20,7 +20,7 @@ from ..utils.json import read_json_file
|
|||||||
from .utils import extract_hash_from_path
|
from .utils import extract_hash_from_path
|
||||||
from .validate import SCHEMA_REPOSITORY_CONFIG
|
from .validate import SCHEMA_REPOSITORY_CONFIG
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class StoreData(CoreSysAttributes):
|
class StoreData(CoreSysAttributes):
|
||||||
|
@ -12,7 +12,7 @@ from ..const import URL_HASSIO_ADDONS, ATTR_URL, ATTR_BRANCH
|
|||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..validate import RE_REPOSITORY
|
from ..validate import RE_REPOSITORY
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GitRepo(CoreSysAttributes):
|
class GitRepo(CoreSysAttributes):
|
||||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
RE_SHA1 = re.compile(r"[a-f0-9]{8}")
|
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:
|
def get_hash_from_repository(name: str) -> str:
|
||||||
|
@ -20,7 +20,7 @@ from .exceptions import (
|
|||||||
SupervisorUpdateError,
|
SupervisorUpdateError,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Supervisor(CoreSysAttributes):
|
class Supervisor(CoreSysAttributes):
|
||||||
|
@ -5,7 +5,7 @@ import logging
|
|||||||
from .coresys import CoreSysAttributes
|
from .coresys import CoreSysAttributes
|
||||||
from .exceptions import HomeAssistantError, CoreDNSError
|
from .exceptions import HomeAssistantError, CoreDNSError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
HASS_WATCHDOG_API = "HASS_WATCHDOG_API"
|
HASS_WATCHDOG_API = "HASS_WATCHDOG_API"
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ from .utils import AsyncThrottle
|
|||||||
from .utils.json import JsonConfig
|
from .utils.json import JsonConfig
|
||||||
from .validate import SCHEMA_UPDATER_CONFIG
|
from .validate import SCHEMA_UPDATER_CONFIG
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Updater(JsonConfig, CoreSysAttributes):
|
class Updater(JsonConfig, CoreSysAttributes):
|
||||||
|
@ -5,7 +5,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
RE_STRING = re.compile(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))")
|
RE_STRING = re.compile(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))")
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import re
|
|||||||
|
|
||||||
from ..exceptions import AppArmorFileError, AppArmorInvalidError
|
from ..exceptions import AppArmorFileError, AppArmorInvalidError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
RE_PROFILE = re.compile(r"^profile ([^ ]+).*$")
|
RE_PROFILE = re.compile(r"^profile ([^ ]+).*$")
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ UTC = pytz.utc
|
|||||||
|
|
||||||
GEOIP_URL = "http://ip-api.com/json/"
|
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.
|
# Copyright (c) Django Software Foundation and individual contributors.
|
||||||
|
@ -1,68 +1,87 @@
|
|||||||
"""DBus implementation with glib."""
|
"""DBus implementation with glib."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import shlex
|
import shlex
|
||||||
import re
|
import re
|
||||||
from signal import SIGINT
|
from signal import SIGINT
|
||||||
|
from typing import Any, Dict, List, Optional, Set
|
||||||
import xml.etree.ElementTree as ET
|
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
|
# 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"(?:boolean|byte|int16|uint16|int32|uint32|handle|int64|uint64|double|"
|
||||||
r"string|objectpath|signature) "
|
r"string|objectpath|signature) "
|
||||||
)
|
)
|
||||||
RE_GVARIANT_VARIANT = re.compile(
|
RE_GVARIANT_VARIANT: re.Match = re.compile(
|
||||||
r"(?<=(?: |{|\[))<((?:'|\").*?(?:'|\")|\d+(?:\.\d+)?)>(?=(?:|]|}|,))"
|
r"(?<=(?: |{|\[))<((?:'|\").*?(?:'|\")|\d+(?:\.\d+)?)>(?=(?:|]|}|,))"
|
||||||
)
|
)
|
||||||
RE_GVARIANT_STRING = re.compile(r"(?<=(?: |{|\[|\())'(.*?)'(?=(?:|]|}|,|\)))")
|
RE_GVARIANT_STRING_ESC: re.Match = re.compile(
|
||||||
RE_GVARIANT_TUPLE_O = re.compile(r"\"[^\"]*?\"|(\()")
|
r"(?<=(?: |{|\[|\())'[^']*?\"[^']*?'(?=(?:|]|}|,|\)))"
|
||||||
RE_GVARIANT_TUPLE_C = 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
|
# Commands for dbus
|
||||||
INTROSPECT = "gdbus introspect --system --dest {bus} " "--object-path {object} --xml"
|
INTROSPECT: str = "gdbus introspect --system --dest {bus} " "--object-path {object} --xml"
|
||||||
CALL = (
|
CALL: str = (
|
||||||
"gdbus call --system --dest {bus} --object-path {object} "
|
"gdbus call --system --dest {bus} --object-path {object} "
|
||||||
"--method {method} {args}"
|
"--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:
|
class DBus:
|
||||||
"""DBus handler."""
|
"""DBus handler."""
|
||||||
|
|
||||||
def __init__(self, bus_name, object_path):
|
def __init__(self, bus_name: str, object_path: str) -> None:
|
||||||
"""Initialize dbus object."""
|
"""Initialize dbus object."""
|
||||||
self.bus_name = bus_name
|
self.bus_name: str = bus_name
|
||||||
self.object_path = object_path
|
self.object_path: str = object_path
|
||||||
self.methods = set()
|
self.methods: Set[str] = set()
|
||||||
self.signals = set()
|
self.signals: Set[str] = set()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def connect(bus_name, object_path):
|
async def connect(bus_name: str, object_path: str) -> DBus:
|
||||||
"""Read object data."""
|
"""Read object data."""
|
||||||
self = DBus(bus_name, object_path)
|
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)
|
_LOGGER.info("Connect to dbus: %s - %s", bus_name, object_path)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def _init_proxy(self):
|
async def _init_proxy(self) -> None:
|
||||||
"""Read interface data."""
|
"""Read interface data."""
|
||||||
command = shlex.split(
|
command = shlex.split(
|
||||||
INTROSPECT.format(bus=self.bus_name, object=self.object_path)
|
INTROSPECT.format(bus=self.bus_name, object=self.object_path)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ask data
|
# 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)
|
data = await self._send(command)
|
||||||
|
|
||||||
# Parse XML
|
# Parse XML
|
||||||
@ -73,7 +92,7 @@ class DBus:
|
|||||||
raise DBusParseError() from None
|
raise DBusParseError() from None
|
||||||
|
|
||||||
# Read available methods
|
# Read available methods
|
||||||
_LOGGER.debug("data: %s", data)
|
_LOGGER.debug("Introspect XML: %s", data)
|
||||||
for interface in xml.findall("./interface"):
|
for interface in xml.findall("./interface"):
|
||||||
interface_name = interface.get("name")
|
interface_name = interface.get("name")
|
||||||
|
|
||||||
@ -88,30 +107,34 @@ class DBus:
|
|||||||
self.signals.add(f"{interface_name}.{signal_name}")
|
self.signals.add(f"{interface_name}.{signal_name}")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_gvariant(raw):
|
def parse_gvariant(raw: str) -> Any:
|
||||||
"""Parse GVariant input to python."""
|
"""Parse GVariant input to python."""
|
||||||
raw = RE_GVARIANT_TYPE.sub("", raw)
|
json_raw: str = RE_GVARIANT_TYPE.sub("", raw)
|
||||||
raw = RE_GVARIANT_VARIANT.sub(r"\1", raw)
|
json_raw = RE_GVARIANT_VARIANT.sub(r"\1", json_raw)
|
||||||
raw = RE_GVARIANT_STRING.sub(r'"\1"', raw)
|
json_raw = RE_GVARIANT_STRING_ESC.sub(
|
||||||
raw = RE_GVARIANT_TUPLE_O.sub(
|
lambda x: x.group(0).replace('"', '\\"'), json_raw
|
||||||
lambda x: x.group(0) if not x.group(1) else "[", raw
|
|
||||||
)
|
)
|
||||||
raw = RE_GVARIANT_TUPLE_C.sub(
|
json_raw = RE_GVARIANT_STRING.sub(r'"\1"', json_raw)
|
||||||
lambda x: x.group(0) if not x.group(1) else "]", 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
|
# No data
|
||||||
if raw.startswith("[]"):
|
if json_raw.startswith("[]"):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return json.loads(raw)
|
return json.loads(json_raw)
|
||||||
except json.JSONDecodeError as err:
|
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
|
raise DBusParseError() from None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def gvariant_args(args):
|
def gvariant_args(args: List[Any]) -> str:
|
||||||
"""Convert args into gvariant."""
|
"""Convert args into gvariant."""
|
||||||
gvariant = ""
|
gvariant = ""
|
||||||
for arg in args:
|
for arg in args:
|
||||||
@ -122,11 +145,11 @@ class DBus:
|
|||||||
elif isinstance(arg, str):
|
elif isinstance(arg, str):
|
||||||
gvariant += f' "{arg}"'
|
gvariant += f' "{arg}"'
|
||||||
else:
|
else:
|
||||||
gvariant += " {}".format(str(arg))
|
gvariant += f" {arg!s}"
|
||||||
|
|
||||||
return gvariant.lstrip()
|
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."""
|
"""Call a dbus method."""
|
||||||
command = shlex.split(
|
command = shlex.split(
|
||||||
CALL.format(
|
CALL.format(
|
||||||
@ -142,10 +165,9 @@ class DBus:
|
|||||||
data = await self._send(command)
|
data = await self._send(command)
|
||||||
|
|
||||||
# Parse and return data
|
# Parse and return data
|
||||||
_LOGGER.debug("Receive from %s: %s", method, data)
|
|
||||||
return self.parse_gvariant(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."""
|
"""Read all properties from interface."""
|
||||||
try:
|
try:
|
||||||
return (await self.call_dbus(DBUS_METHOD_GETALL, interface))[0]
|
return (await self.call_dbus(DBUS_METHOD_GETALL, interface))[0]
|
||||||
@ -153,7 +175,7 @@ class DBus:
|
|||||||
_LOGGER.error("No attributes returned for %s", interface)
|
_LOGGER.error("No attributes returned for %s", interface)
|
||||||
raise DBusFatalError from None
|
raise DBusFatalError from None
|
||||||
|
|
||||||
async def _send(self, command):
|
async def _send(self, command: List[str]) -> str:
|
||||||
"""Send command over dbus."""
|
"""Send command over dbus."""
|
||||||
# Run command
|
# Run command
|
||||||
_LOGGER.debug("Send dbus command: %s", command)
|
_LOGGER.debug("Send dbus command: %s", command)
|
||||||
@ -171,12 +193,19 @@ class DBus:
|
|||||||
raise DBusFatalError() from None
|
raise DBusFatalError() from None
|
||||||
|
|
||||||
# Success?
|
# Success?
|
||||||
if proc.returncode != 0:
|
if proc.returncode == 0:
|
||||||
_LOGGER.error("DBus return error: %s", error)
|
return data.decode()
|
||||||
raise DBusFatalError()
|
|
||||||
|
|
||||||
# End
|
# Filter error
|
||||||
return data.decode()
|
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()
|
||||||
|
|
||||||
def attach_signals(self, filters=None):
|
def attach_signals(self, filters=None):
|
||||||
"""Generate a signals wrapper."""
|
"""Generate a signals wrapper."""
|
||||||
@ -189,7 +218,7 @@ class DBus:
|
|||||||
async for signal in signals:
|
async for signal in signals:
|
||||||
return signal
|
return signal
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name: str) -> DBusCallWrapper:
|
||||||
"""Mapping to dbus method."""
|
"""Mapping to dbus method."""
|
||||||
return getattr(DBusCallWrapper(self, self.bus_name), name)
|
return getattr(DBusCallWrapper(self, self.bus_name), name)
|
||||||
|
|
||||||
@ -197,17 +226,17 @@ class DBus:
|
|||||||
class DBusCallWrapper:
|
class DBusCallWrapper:
|
||||||
"""Wrapper a DBus interface for a call."""
|
"""Wrapper a DBus interface for a call."""
|
||||||
|
|
||||||
def __init__(self, dbus, interface):
|
def __init__(self, dbus: DBus, interface: str) -> None:
|
||||||
"""Initialize wrapper."""
|
"""Initialize wrapper."""
|
||||||
self.dbus = dbus
|
self.dbus: DBus = dbus
|
||||||
self.interface = interface
|
self.interface: str = interface
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self) -> None:
|
||||||
"""Should never be called."""
|
"""Should never be called."""
|
||||||
_LOGGER.error("DBus method %s not exists!", self.interface)
|
_LOGGER.error("DBus method %s not exists!", self.interface)
|
||||||
raise DBusFatalError()
|
raise DBusFatalError()
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name: str):
|
||||||
"""Mapping to dbus method."""
|
"""Mapping to dbus method."""
|
||||||
interface = f"{self.interface}.{name}"
|
interface = f"{self.interface}.{name}"
|
||||||
|
|
||||||
@ -227,11 +256,11 @@ class DBusCallWrapper:
|
|||||||
class DBusSignalWrapper:
|
class DBusSignalWrapper:
|
||||||
"""Process Signals."""
|
"""Process Signals."""
|
||||||
|
|
||||||
def __init__(self, dbus, signals=None):
|
def __init__(self, dbus: DBus, signals: Optional[str] = None):
|
||||||
"""Initialize dbus signal wrapper."""
|
"""Initialize dbus signal wrapper."""
|
||||||
self.dbus = dbus
|
self.dbus: DBus = dbus
|
||||||
self._signals = signals
|
self._signals: Optional[str] = signals
|
||||||
self._proc = None
|
self._proc: Optional[asyncio.Process] = None
|
||||||
|
|
||||||
async def __aenter__(self):
|
async def __aenter__(self):
|
||||||
"""Start monitor events."""
|
"""Start monitor events."""
|
||||||
|
@ -9,7 +9,7 @@ from voluptuous.humanize import humanize_error
|
|||||||
|
|
||||||
from ..exceptions import JsonFileError
|
from ..exceptions import JsonFileError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def write_json_file(jsonfile: Path, data: Any) -> None:
|
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