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:
Pascal Vizeli 2021-02-22 11:22:36 +01:00 committed by GitHub
parent 14ec61f9bd
commit 2b45c059e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 0 deletions

View File

@ -45,6 +45,7 @@ from ..const import (
ATTR_PORTS,
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_REALTIME,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
@ -396,6 +397,11 @@ class AddonModel(CoreSysAttributes, ABC):
"""Return True if the add-on access to 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
def with_full_access(self) -> bool:
"""Return True if the add-on want full access to hardware."""

View File

@ -59,6 +59,7 @@ from ..const import (
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_PROTECTED,
ATTR_REALTIME,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
@ -263,6 +264,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_UART, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICETREE, 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_ROLE, default=ROLE_DEFAULT): vol.In(ROLE_ALL),
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),

View File

@ -289,6 +289,7 @@ ATTR_FREQUENCY = "frequency"
ATTR_ACCESSPOINTS = "accesspoints"
ATTR_UNHEALTHY = "unhealthy"
ATTR_OTA = "ota"
ATTR_REALTIME = "realtime"
PROVIDE_SERVICE = "provide"
NEED_SERVICE = "need"

View File

@ -250,11 +250,36 @@ class DockerAddon(DockerInterface):
if self.addon.with_kernel_modules:
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
if capabilities:
return [cap.value for cap in capabilities]
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
def volumes(self) -> Dict[str, Dict[str, str]]:
"""Generate volumes for mappings."""
@ -416,6 +441,8 @@ class DockerAddon(DockerInterface):
extra_hosts=self.network_mapping,
device_cgroup_rules=self.cgroups_rules,
cap_add=self.capabilities,
ulimits=self.ulimits,
cpu_rt_runtime=self.cpu_rt_runtime,
security_opt=self.security_opt,
environment=self.environment,
volumes=self.volumes,

View File

@ -2,6 +2,8 @@
import logging
from typing import Dict, List
import docker
from ..const import ENV_TIME, MACHINE_ID
from ..coresys import CoreSysAttributes
from ..docker.const import Capabilities
@ -54,6 +56,11 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
"""Generate needed capabilities."""
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:
"""Run Docker image.
@ -75,6 +82,8 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
hostname=self.name.replace("_", "-"),
detach=True,
cap_add=self.capabilities,
ulimits=self.ulimits,
cpu_rt_runtime=950000,
device_cgroup_rules=self.cgroups_rules,
environment={ENV_TIME: self.sys_config.timezone},
volumes=self.volumes,