1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-04-18 07:35:22 +01:00

Centralize OSError bad message handling in ResolutionManager (#6641)

Add check_oserror() method to ResolutionManager with an extensible
errno-to-unhealthy-reason mapping. Replace ~20 inline
`if err.errno == errno.EBADMSG` checks across 14 files with a single
call to self.sys_resolution.check_oserror(err). This makes it easy to
add handling for additional filesystem errors (e.g. EIO, ENOSPC) in
one place.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-03-25 16:47:36 +01:00
committed by GitHub
parent 2b2aca873b
commit c0cca1ff8b
14 changed files with 51 additions and 123 deletions

View File

@@ -5,7 +5,6 @@ from collections.abc import Awaitable
from contextlib import suppress from contextlib import suppress
from copy import deepcopy from copy import deepcopy
from datetime import datetime from datetime import datetime
import errno
from functools import partial from functools import partial
from ipaddress import IPv4Address from ipaddress import IPv4Address
import logging import logging
@@ -89,7 +88,7 @@ from ..hardware.data import Device
from ..homeassistant.const import WSEvent from ..homeassistant.const import WSEvent
from ..jobs.const import JobConcurrency, JobThrottle from ..jobs.const import JobConcurrency, JobThrottle
from ..jobs.decorator import Job from ..jobs.decorator import Job
from ..resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason from ..resolution.const import ContextType, IssueType, SuggestionType
from ..resolution.data import Issue from ..resolution.data import Issue
from ..store.addon import AddonStore from ..store.addon import AddonStore
from ..utils import check_port from ..utils import check_port
@@ -1027,10 +1026,7 @@ class Addon(AddonModel):
try: try:
await self.sys_run_in_executor(write_pulse_config) await self.sys_run_in_executor(write_pulse_config)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error( _LOGGER.error(
"Add-on %s can't write pulse/client.config: %s", self.slug, err "Add-on %s can't write pulse/client.config: %s", self.slug, err
) )

View File

@@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import errno
from io import BufferedWriter from io import BufferedWriter
import logging import logging
from pathlib import Path from pathlib import Path
@@ -50,7 +49,6 @@ from ..const import (
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APIForbidden, APINotFound from ..exceptions import APIError, APIForbidden, APINotFound
from ..mounts.const import MountUsage from ..mounts.const import MountUsage
from ..resolution.const import UnhealthyReason
from .const import ( from .const import (
ATTR_ADDITIONAL_LOCATIONS, ATTR_ADDITIONAL_LOCATIONS,
ATTR_BACKGROUND, ATTR_BACKGROUND,
@@ -518,13 +516,8 @@ class APIBackups(CoreSysAttributes):
) )
) )
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG and location in { if location in {LOCATION_CLOUD_BACKUP, None}:
LOCATION_CLOUD_BACKUP, self.sys_resolution.check_oserror(err)
None,
}:
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't write new backup file: %s", err) _LOGGER.error("Can't write new backup file: %s", err)
return False return False

View File

@@ -210,13 +210,11 @@ class BackupManager(FileConfiguration, JobGroup):
try: try:
return await self.sys_run_in_executor(find_backups) return await self.sys_run_in_executor(find_backups)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG and path in { if path in {
self.sys_config.path_backup, self.sys_config.path_backup,
self.sys_config.path_core_backup, self.sys_config.path_core_backup,
}: }:
self.sys_resolution.add_unhealthy_reason( self.sys_resolution.check_oserror(err)
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Could not list backups from %s: %s", path.as_posix(), err) _LOGGER.error("Could not list backups from %s: %s", path.as_posix(), err)
return [] return []
@@ -365,13 +363,8 @@ class BackupManager(FileConfiguration, JobGroup):
) from err ) from err
except OSError as err: except OSError as err:
msg = f"Could delete backup at {backup_tarfile.as_posix()}: {err!s}" msg = f"Could delete backup at {backup_tarfile.as_posix()}: {err!s}"
if err.errno == errno.EBADMSG and location in { if location in {None, LOCATION_CLOUD_BACKUP}:
None, self.sys_resolution.check_oserror(err)
LOCATION_CLOUD_BACKUP,
}:
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise BackupError(msg, _LOGGER.error) from err raise BackupError(msg, _LOGGER.error) from err
# If backup has been removed from all locations, remove it from cache # If backup has been removed from all locations, remove it from cache
@@ -403,12 +396,10 @@ class BackupManager(FileConfiguration, JobGroup):
return (location_name, Path(path)) return (location_name, Path(path))
except OSError as err: except OSError as err:
msg = f"Could not copy backup to {location_name} due to: {err!s}" msg = f"Could not copy backup to {location_name} due to: {err!s}"
if location in {LOCATION_CLOUD_BACKUP, None}:
if err.errno == errno.EBADMSG and location in { self.sys_resolution.check_oserror(err)
LOCATION_CLOUD_BACKUP, if err.errno == errno.EBADMSG:
None, raise BackupDataDiskBadMessageError(msg, _LOGGER.error) from err
}:
raise BackupDataDiskBadMessageError(msg, _LOGGER.error) from err
raise BackupError(msg, _LOGGER.error) from err raise BackupError(msg, _LOGGER.error) from err
@Job(name="backup_copy_to_additional_locations", cleanup=False) @Job(name="backup_copy_to_additional_locations", cleanup=False)
@@ -468,10 +459,8 @@ class BackupManager(FileConfiguration, JobGroup):
try: try:
await self.sys_run_in_executor(backup.tarfile.rename, tar_file) await self.sys_run_in_executor(backup.tarfile.rename, tar_file)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG and location in {LOCATION_CLOUD_BACKUP, None}: if location in {LOCATION_CLOUD_BACKUP, None}:
self.sys_resolution.add_unhealthy_reason( self.sys_resolution.check_oserror(err)
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't move backup file to storage: %s", err) _LOGGER.error("Can't move backup file to storage: %s", err)
return None return None

View File

@@ -6,7 +6,6 @@ import asyncio
from collections.abc import Mapping from collections.abc import Mapping
from contextlib import suppress from contextlib import suppress
from dataclasses import dataclass from dataclasses import dataclass
import errno
from http import HTTPStatus from http import HTTPStatus
from io import BufferedReader, BufferedWriter from io import BufferedReader, BufferedWriter
from ipaddress import IPv4Address from ipaddress import IPv4Address
@@ -47,7 +46,6 @@ from ..exceptions import (
DockerNotFound, DockerNotFound,
DockerRequestError, DockerRequestError,
) )
from ..resolution.const import UnhealthyReason
from ..utils.common import FileConfiguration from ..utils.common import FileConfiguration
from ..validate import SCHEMA_DOCKER_CONFIG from ..validate import SCHEMA_DOCKER_CONFIG
from .const import ( from .const import (
@@ -1015,10 +1013,7 @@ class DockerAPI(CoreSysAttributes):
f"Can't import image from tar: {err}", _LOGGER.error f"Can't import image from tar: {err}", _LOGGER.error
) from err ) from err
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise DockerError( raise DockerError(
f"Can't read tar file {tar_file}: {err}", _LOGGER.error f"Can't read tar file {tar_file}: {err}", _LOGGER.error
) from err ) from err
@@ -1071,10 +1066,7 @@ class DockerAPI(CoreSysAttributes):
f"Can't fetch image {image}:{version}: {err}", _LOGGER.error f"Can't fetch image {image}:{version}: {err}", _LOGGER.error
) from err ) from err
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise DockerError( raise DockerError(
f"Can't write tar file {tar_file}: {err}", _LOGGER.error f"Can't write tar file {tar_file}: {err}", _LOGGER.error
) from err ) from err

View File

@@ -13,7 +13,6 @@ from ..exceptions import (
DBusObjectError, DBusObjectError,
HardwareNotFound, HardwareNotFound,
) )
from ..resolution.const import UnhealthyReason
from .const import UdevSubsystem from .const import UdevSubsystem
from .data import Device from .data import Device
@@ -114,10 +113,8 @@ class HwDisk(CoreSysAttributes):
_LOGGER.warning("File not found: %s", child.as_posix()) _LOGGER.warning("File not found: %s", child.as_posix())
continue continue
except OSError as err: except OSError as err:
self.sys_resolution.check_oserror(err)
if err.errno == errno.EBADMSG: if err.errno == errno.EBADMSG:
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
break break
continue continue

View File

@@ -1,7 +1,6 @@
"""Home Assistant control object.""" """Home Assistant control object."""
import asyncio import asyncio
import errno
from ipaddress import IPv4Address from ipaddress import IPv4Address
import logging import logging
from pathlib import Path, PurePath from pathlib import Path, PurePath
@@ -47,7 +46,6 @@ from ..exceptions import (
from ..hardware.const import PolicyGroup from ..hardware.const import PolicyGroup
from ..hardware.data import Device from ..hardware.data import Device
from ..jobs.decorator import Job from ..jobs.decorator import Job
from ..resolution.const import UnhealthyReason
from ..utils import remove_folder, remove_folder_with_excludes from ..utils import remove_folder, remove_folder_with_excludes
from ..utils.common import FileConfiguration from ..utils.common import FileConfiguration
from ..utils.json import read_json_file, write_json_file from ..utils.json import read_json_file, write_json_file
@@ -340,10 +338,7 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
try: try:
await self.sys_run_in_executor(write_pulse_config) await self.sys_run_in_executor(write_pulse_config)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Home Assistant can't write pulse/client.config: %s", err) _LOGGER.error("Home Assistant can't write pulse/client.config: %s", err)
else: else:
_LOGGER.info("Update pulse/client.config: %s", self.path_pulse) _LOGGER.info("Update pulse/client.config: %s", self.path_pulse)

View File

@@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
from contextlib import suppress from contextlib import suppress
import errno
import logging import logging
from pathlib import Path from pathlib import Path
import shutil import shutil
@@ -12,7 +11,7 @@ from awesomeversion import AwesomeVersion
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import DBusError, HostAppArmorError from ..exceptions import DBusError, HostAppArmorError
from ..resolution.const import UnhealthyReason, UnsupportedReason from ..resolution.const import UnsupportedReason
from ..utils.apparmor import validate_profile from ..utils.apparmor import validate_profile
from .const import HostFeature from .const import HostFeature
@@ -89,10 +88,7 @@ class AppArmorControl(CoreSysAttributes):
try: try:
await self.sys_run_in_executor(shutil.copyfile, profile_file, dest_profile) await self.sys_run_in_executor(shutil.copyfile, profile_file, dest_profile)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise HostAppArmorError( raise HostAppArmorError(
f"Can't copy {profile_file}: {err}", _LOGGER.error f"Can't copy {profile_file}: {err}", _LOGGER.error
) from err ) from err
@@ -116,10 +112,7 @@ class AppArmorControl(CoreSysAttributes):
try: try:
await self.sys_run_in_executor(profile_file.unlink) await self.sys_run_in_executor(profile_file.unlink)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise HostAppArmorError( raise HostAppArmorError(
f"Can't remove profile: {err}", _LOGGER.error f"Can't remove profile: {err}", _LOGGER.error
) from err ) from err
@@ -134,10 +127,7 @@ class AppArmorControl(CoreSysAttributes):
try: try:
shutil.copy(profile_file, backup_file) shutil.copy(profile_file, backup_file)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise HostAppArmorError( raise HostAppArmorError(
f"Can't backup profile {profile_name}: {err}", _LOGGER.error f"Can't backup profile {profile_name}: {err}", _LOGGER.error
) from err ) from err

View File

@@ -2,7 +2,6 @@
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime from datetime import datetime
import errno
import logging import logging
from pathlib import Path, PurePath from pathlib import Path, PurePath
from typing import cast from typing import cast
@@ -23,7 +22,6 @@ from ..exceptions import (
) )
from ..jobs.const import JobConcurrency, JobCondition from ..jobs.const import JobConcurrency, JobCondition
from ..jobs.decorator import Job from ..jobs.decorator import Job
from ..resolution.const import UnhealthyReason
from ..utils.sentry import async_capture_exception from ..utils.sentry import async_capture_exception
from .data_disk import DataDisk from .data_disk import DataDisk
@@ -214,10 +212,7 @@ class OSManager(CoreSysAttributes):
) from err ) from err
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise HassOSUpdateError( raise HassOSUpdateError(
f"Can't write OTA file: {err!s}", _LOGGER.error f"Can't write OTA file: {err!s}", _LOGGER.error
) from err ) from err

View File

@@ -3,7 +3,6 @@
Code: https://github.com/home-assistant/plugin-audio Code: https://github.com/home-assistant/plugin-audio
""" """
import errno
import logging import logging
from pathlib import Path, PurePath from pathlib import Path, PurePath
import shutil import shutil
@@ -26,7 +25,6 @@ from ..exceptions import (
) )
from ..jobs.const import JobThrottle from ..jobs.const import JobThrottle
from ..jobs.decorator import Job from ..jobs.decorator import Job
from ..resolution.const import UnhealthyReason
from ..utils.json import write_json_file from ..utils.json import write_json_file
from ..utils.sentry import async_capture_exception from ..utils.sentry import async_capture_exception
from .base import PluginBase from .base import PluginBase
@@ -94,11 +92,7 @@ class PluginAudio(PluginBase):
) )
) )
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't read pulse-client.tmpl: %s", err) _LOGGER.error("Can't read pulse-client.tmpl: %s", err)
await super().load() await super().load()
@@ -113,10 +107,7 @@ class PluginAudio(PluginBase):
try: try:
await self.sys_run_in_executor(setup_default_asound) await self.sys_run_in_executor(setup_default_asound)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't create default asound: %s", err) _LOGGER.error("Can't create default asound: %s", err)
@Job( @Job(

View File

@@ -5,7 +5,6 @@ Code: https://github.com/home-assistant/plugin-dns
import asyncio import asyncio
from contextlib import suppress from contextlib import suppress
import errno
from ipaddress import IPv4Address from ipaddress import IPv4Address
import logging import logging
from pathlib import Path from pathlib import Path
@@ -33,7 +32,7 @@ from ..exceptions import (
) )
from ..jobs.const import JobThrottle from ..jobs.const import JobThrottle
from ..jobs.decorator import Job from ..jobs.decorator import Job
from ..resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason from ..resolution.const import ContextType, IssueType, SuggestionType
from ..utils.json import write_json_file from ..utils.json import write_json_file
from ..utils.sentry import async_capture_exception from ..utils.sentry import async_capture_exception
from ..validate import dns_url from ..validate import dns_url
@@ -232,10 +231,7 @@ class PluginDns(PluginBase):
await self.sys_run_in_executor(RESOLV_TMPL.read_text, encoding="utf-8") await self.sys_run_in_executor(RESOLV_TMPL.read_text, encoding="utf-8")
) )
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't read resolve.tmpl: %s", err) _LOGGER.error("Can't read resolve.tmpl: %s", err)
try: try:
@@ -243,10 +239,7 @@ class PluginDns(PluginBase):
await self.sys_run_in_executor(HOSTS_TMPL.read_text, encoding="utf-8") await self.sys_run_in_executor(HOSTS_TMPL.read_text, encoding="utf-8")
) )
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't read hosts.tmpl: %s", err) _LOGGER.error("Can't read hosts.tmpl: %s", err)
await self._init_hosts() await self._init_hosts()
@@ -448,10 +441,7 @@ class PluginDns(PluginBase):
self.hosts.write_text, data, encoding="utf-8" self.hosts.write_text, data, encoding="utf-8"
) )
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise CoreDNSError(f"Can't update hosts: {err}", _LOGGER.error) from err raise CoreDNSError(f"Can't update hosts: {err}", _LOGGER.error) from err
async def add_host( async def add_host(
@@ -533,10 +523,7 @@ class PluginDns(PluginBase):
try: try:
await self.sys_run_in_executor(resolv_conf.write_text, data) await self.sys_run_in_executor(resolv_conf.write_text, data)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.warning("Can't write/update %s: %s", resolv_conf, err) _LOGGER.warning("Can't write/update %s: %s", resolv_conf, err)
return return

View File

@@ -1,5 +1,6 @@
"""Supervisor resolution center.""" """Supervisor resolution center."""
import errno
import logging import logging
from typing import Any from typing import Any
@@ -153,6 +154,19 @@ class ResolutionManager(FileConfiguration, CoreSysAttributes):
attr.asdict(HealthChanged(False, self.unhealthy)), attr.asdict(HealthChanged(False, self.unhealthy)),
) )
_OSERROR_UNHEALTHY_REASONS: dict[int, UnhealthyReason] = {
errno.EBADMSG: UnhealthyReason.OSERROR_BAD_MESSAGE,
}
def check_oserror(self, err: OSError) -> None:
"""Check OSError for known filesystem issues and mark system unhealthy.
Must only be used on OSErrors that are caused by file operation on a
local path.
"""
if err.errno in self._OSERROR_UNHEALTHY_REASONS:
self.add_unhealthy_reason(self._OSERROR_UNHEALTHY_REASONS[err.errno])
def _make_issue_message(self, issue: Issue) -> dict[str, Any]: def _make_issue_message(self, issue: Issue) -> dict[str, Any]:
"""Make issue into message for core.""" """Make issue into message for core."""
return attr.asdict(issue) | { return attr.asdict(issue) | {

View File

@@ -22,7 +22,7 @@ from ..const import (
) )
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import ConfigurationFileError from ..exceptions import ConfigurationFileError
from ..resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason from ..resolution.const import ContextType, IssueType, SuggestionType
from ..utils.common import find_one_filetype, read_json_or_yaml_file from ..utils.common import find_one_filetype, read_json_or_yaml_file
from ..utils.json import read_json_file from ..utils.json import read_json_file
from .utils import extract_hash_from_path from .utils import extract_hash_from_path
@@ -164,11 +164,8 @@ class StoreData(CoreSysAttributes):
addon_list = await self.sys_run_in_executor(_get_addons_list) addon_list = await self.sys_run_in_executor(_get_addons_list)
except OSError as err: except OSError as err:
suggestion = None suggestion = None
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason( if err.errno != errno.EBADMSG and repository != REPOSITORY_LOCAL:
UnhealthyReason.OSERROR_BAD_MESSAGE
)
elif repository != REPOSITORY_LOCAL:
suggestion = [SuggestionType.EXECUTE_RESET] suggestion = [SuggestionType.EXECUTE_RESET]
self.sys_resolution.create_issue( self.sys_resolution.create_issue(
IssueType.CORRUPT_REPOSITORY, IssueType.CORRUPT_REPOSITORY,

View File

@@ -1,7 +1,6 @@
"""Init file for Supervisor add-on Git.""" """Init file for Supervisor add-on Git."""
import asyncio import asyncio
import errno
import functools as ft import functools as ft
import logging import logging
from pathlib import Path from pathlib import Path
@@ -13,7 +12,7 @@ from ..const import ATTR_BRANCH, ATTR_URL
from ..coresys import CoreSys, CoreSysAttributes from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import StoreGitCloneError, StoreGitError, StoreJobError from ..exceptions import StoreGitCloneError, StoreGitError, StoreJobError
from ..jobs.decorator import Job, JobCondition from ..jobs.decorator import Job, JobCondition
from ..resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason from ..resolution.const import ContextType, IssueType, SuggestionType
from ..utils import directory_missing_or_empty, remove_folder from ..utils import directory_missing_or_empty, remove_folder
from .validate import RE_REPOSITORY from .validate import RE_REPOSITORY
@@ -112,10 +111,7 @@ class GitRepo(CoreSysAttributes):
try: try:
await self.sys_run_in_executor(move_clone) await self.sys_run_in_executor(move_clone)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise StoreGitCloneError( raise StoreGitCloneError(
f"Can't move clone due to: {err!s}", _LOGGER.error f"Can't move clone due to: {err!s}", _LOGGER.error
) from err ) from err

View File

@@ -3,7 +3,6 @@
from collections.abc import Awaitable from collections.abc import Awaitable
from contextlib import suppress from contextlib import suppress
from datetime import timedelta from datetime import timedelta
import errno
from ipaddress import IPv4Address from ipaddress import IPv4Address
import logging import logging
from pathlib import Path from pathlib import Path
@@ -33,7 +32,7 @@ from .exceptions import (
from .jobs import ChildJobSyncFilter from .jobs import ChildJobSyncFilter
from .jobs.const import JobCondition, JobThrottle from .jobs.const import JobCondition, JobThrottle
from .jobs.decorator import Job from .jobs.decorator import Job
from .resolution.const import ContextType, IssueType, UnhealthyReason from .resolution.const import ContextType, IssueType
from .utils.sentry import async_capture_exception from .utils.sentry import async_capture_exception
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -162,10 +161,7 @@ class Supervisor(CoreSysAttributes):
await self.sys_host.apparmor.load_profile("hassio-supervisor", profile_file) await self.sys_host.apparmor.load_profile("hassio-supervisor", profile_file)
except OSError as err: except OSError as err:
if err.errno == errno.EBADMSG: self.sys_resolution.check_oserror(err)
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
raise SupervisorAppArmorError( raise SupervisorAppArmorError(
f"Can't write temporary profile: {err!s}", _LOGGER.error f"Can't write temporary profile: {err!s}", _LOGGER.error
) from err ) from err