mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-20 07:36:29 +00:00
Support realtime scheduling for add-ons (#2593)
* Support realtime scheduling for add-ons * support on audio * address comments from @jens-maus
This commit is contained in:
parent
14ec61f9bd
commit
2b45c059e0
@ -45,6 +45,7 @@ from ..const import (
|
|||||||
ATTR_PORTS,
|
ATTR_PORTS,
|
||||||
ATTR_PORTS_DESCRIPTION,
|
ATTR_PORTS_DESCRIPTION,
|
||||||
ATTR_PRIVILEGED,
|
ATTR_PRIVILEGED,
|
||||||
|
ATTR_REALTIME,
|
||||||
ATTR_REPOSITORY,
|
ATTR_REPOSITORY,
|
||||||
ATTR_SCHEMA,
|
ATTR_SCHEMA,
|
||||||
ATTR_SERVICES,
|
ATTR_SERVICES,
|
||||||
@ -396,6 +397,11 @@ class AddonModel(CoreSysAttributes, ABC):
|
|||||||
"""Return True if the add-on access to kernel modules."""
|
"""Return True if the add-on access to kernel modules."""
|
||||||
return self.data[ATTR_KERNEL_MODULES]
|
return self.data[ATTR_KERNEL_MODULES]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def with_realtime(self) -> bool:
|
||||||
|
"""Return True if the add-on need realtime schedule functions."""
|
||||||
|
return self.data[ATTR_REALTIME]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def with_full_access(self) -> bool:
|
def with_full_access(self) -> bool:
|
||||||
"""Return True if the add-on want full access to hardware."""
|
"""Return True if the add-on want full access to hardware."""
|
||||||
|
@ -59,6 +59,7 @@ from ..const import (
|
|||||||
ATTR_PORTS_DESCRIPTION,
|
ATTR_PORTS_DESCRIPTION,
|
||||||
ATTR_PRIVILEGED,
|
ATTR_PRIVILEGED,
|
||||||
ATTR_PROTECTED,
|
ATTR_PROTECTED,
|
||||||
|
ATTR_REALTIME,
|
||||||
ATTR_REPOSITORY,
|
ATTR_REPOSITORY,
|
||||||
ATTR_SCHEMA,
|
ATTR_SCHEMA,
|
||||||
ATTR_SERVICES,
|
ATTR_SERVICES,
|
||||||
@ -263,6 +264,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
|
|||||||
vol.Optional(ATTR_UART, default=False): vol.Boolean(),
|
vol.Optional(ATTR_UART, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
|
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_KERNEL_MODULES, default=False): vol.Boolean(),
|
vol.Optional(ATTR_KERNEL_MODULES, default=False): vol.Boolean(),
|
||||||
|
vol.Optional(ATTR_REALTIME, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),
|
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_HASSIO_ROLE, default=ROLE_DEFAULT): vol.In(ROLE_ALL),
|
vol.Optional(ATTR_HASSIO_ROLE, default=ROLE_DEFAULT): vol.In(ROLE_ALL),
|
||||||
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
|
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
|
||||||
|
@ -289,6 +289,7 @@ ATTR_FREQUENCY = "frequency"
|
|||||||
ATTR_ACCESSPOINTS = "accesspoints"
|
ATTR_ACCESSPOINTS = "accesspoints"
|
||||||
ATTR_UNHEALTHY = "unhealthy"
|
ATTR_UNHEALTHY = "unhealthy"
|
||||||
ATTR_OTA = "ota"
|
ATTR_OTA = "ota"
|
||||||
|
ATTR_REALTIME = "realtime"
|
||||||
|
|
||||||
PROVIDE_SERVICE = "provide"
|
PROVIDE_SERVICE = "provide"
|
||||||
NEED_SERVICE = "need"
|
NEED_SERVICE = "need"
|
||||||
|
@ -250,11 +250,36 @@ class DockerAddon(DockerInterface):
|
|||||||
if self.addon.with_kernel_modules:
|
if self.addon.with_kernel_modules:
|
||||||
capabilities.add(Capabilities.SYS_MODULE)
|
capabilities.add(Capabilities.SYS_MODULE)
|
||||||
|
|
||||||
|
# Need schedule functions
|
||||||
|
if self.addon.with_realtime:
|
||||||
|
capabilities.add(Capabilities.SYS_NICE)
|
||||||
|
|
||||||
# Return None if no capabilities is present
|
# Return None if no capabilities is present
|
||||||
if capabilities:
|
if capabilities:
|
||||||
return [cap.value for cap in capabilities]
|
return [cap.value for cap in capabilities]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ulimits(self) -> Optional[List[docker.types.Ulimit]]:
|
||||||
|
"""Generate ulimits for add-on."""
|
||||||
|
limits: List[docker.types.Ulimit] = []
|
||||||
|
|
||||||
|
# Need schedule functions
|
||||||
|
if self.addon.with_realtime:
|
||||||
|
limits.append(docker.types.Ulimit(name="rtprio", soft=99))
|
||||||
|
|
||||||
|
# Return None if no capabilities is present
|
||||||
|
if limits:
|
||||||
|
return limits
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_rt_runtime(self) -> Optional[int]:
|
||||||
|
"""Limit CPU real-time runtime in microseconds."""
|
||||||
|
if self.addon.with_realtime:
|
||||||
|
return 950000
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def volumes(self) -> Dict[str, Dict[str, str]]:
|
def volumes(self) -> Dict[str, Dict[str, str]]:
|
||||||
"""Generate volumes for mappings."""
|
"""Generate volumes for mappings."""
|
||||||
@ -416,6 +441,8 @@ class DockerAddon(DockerInterface):
|
|||||||
extra_hosts=self.network_mapping,
|
extra_hosts=self.network_mapping,
|
||||||
device_cgroup_rules=self.cgroups_rules,
|
device_cgroup_rules=self.cgroups_rules,
|
||||||
cap_add=self.capabilities,
|
cap_add=self.capabilities,
|
||||||
|
ulimits=self.ulimits,
|
||||||
|
cpu_rt_runtime=self.cpu_rt_runtime,
|
||||||
security_opt=self.security_opt,
|
security_opt=self.security_opt,
|
||||||
environment=self.environment,
|
environment=self.environment,
|
||||||
volumes=self.volumes,
|
volumes=self.volumes,
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
|
import docker
|
||||||
|
|
||||||
from ..const import ENV_TIME, MACHINE_ID
|
from ..const import ENV_TIME, MACHINE_ID
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..docker.const import Capabilities
|
from ..docker.const import Capabilities
|
||||||
@ -54,6 +56,11 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
|
|||||||
"""Generate needed capabilities."""
|
"""Generate needed capabilities."""
|
||||||
return [cap.value for cap in (Capabilities.SYS_NICE, Capabilities.SYS_RESOURCE)]
|
return [cap.value for cap in (Capabilities.SYS_NICE, Capabilities.SYS_RESOURCE)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ulimits(self) -> List[docker.types.Ulimit]:
|
||||||
|
"""Generate ulimits for audio."""
|
||||||
|
return [docker.types.Ulimit(name="rtprio", soft=99)]
|
||||||
|
|
||||||
def _run(self) -> None:
|
def _run(self) -> None:
|
||||||
"""Run Docker image.
|
"""Run Docker image.
|
||||||
|
|
||||||
@ -75,6 +82,8 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
|
|||||||
hostname=self.name.replace("_", "-"),
|
hostname=self.name.replace("_", "-"),
|
||||||
detach=True,
|
detach=True,
|
||||||
cap_add=self.capabilities,
|
cap_add=self.capabilities,
|
||||||
|
ulimits=self.ulimits,
|
||||||
|
cpu_rt_runtime=950000,
|
||||||
device_cgroup_rules=self.cgroups_rules,
|
device_cgroup_rules=self.cgroups_rules,
|
||||||
environment={ENV_TIME: self.sys_config.timezone},
|
environment={ENV_TIME: self.sys_config.timezone},
|
||||||
volumes=self.volumes,
|
volumes=self.volumes,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user