mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-20 07:36:29 +00:00
Temporary directory to executor (#5673)
* Move temporary directory usage to executor * Use temp_folder.name in Path constructor
This commit is contained in:
parent
c5d4ebcd48
commit
151d4bdd73
@ -977,11 +977,21 @@ class Addon(AddonModel):
|
||||
return
|
||||
|
||||
# Need install/update
|
||||
with TemporaryDirectory(dir=self.sys_config.path_tmp) as tmp_folder:
|
||||
profile_file = Path(tmp_folder, "apparmor.txt")
|
||||
tmp_folder: TemporaryDirectory | None = None
|
||||
|
||||
def install_update_profile() -> Path:
|
||||
nonlocal tmp_folder
|
||||
tmp_folder = TemporaryDirectory(dir=self.sys_config.path_tmp)
|
||||
profile_file = Path(tmp_folder.name, "apparmor.txt")
|
||||
adjust_profile(self.slug, self.path_apparmor, profile_file)
|
||||
return profile_file
|
||||
|
||||
try:
|
||||
profile_file = await self.sys_run_in_executor(install_update_profile)
|
||||
await self.sys_host.apparmor.load_profile(self.slug, profile_file)
|
||||
finally:
|
||||
if tmp_folder:
|
||||
await self.sys_run_in_executor(tmp_folder.cleanup)
|
||||
|
||||
async def uninstall_apparmor(self) -> None:
|
||||
"""Remove AppArmor profile for Add-on."""
|
||||
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
import errno
|
||||
from io import IOBase
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import re
|
||||
@ -518,29 +519,28 @@ class APIBackups(CoreSysAttributes):
|
||||
except vol.Invalid as ex:
|
||||
raise APIError(humanize_error(filename, ex)) from None
|
||||
|
||||
with TemporaryDirectory(dir=tmp_path.as_posix()) as temp_dir:
|
||||
tar_file = Path(temp_dir, "backup.tar")
|
||||
temp_dir: TemporaryDirectory | None = None
|
||||
backup_file_stream: IOBase | None = None
|
||||
|
||||
def open_backup_file() -> Path:
|
||||
nonlocal temp_dir, backup_file_stream
|
||||
temp_dir = TemporaryDirectory(dir=tmp_path.as_posix())
|
||||
tar_file = Path(temp_dir.name, "backup.tar")
|
||||
backup_file_stream = tar_file.open("wb")
|
||||
return tar_file
|
||||
|
||||
def close_backup_file() -> None:
|
||||
if backup_file_stream:
|
||||
backup_file_stream.close()
|
||||
if temp_dir:
|
||||
temp_dir.cleanup()
|
||||
|
||||
try:
|
||||
reader = await request.multipart()
|
||||
contents = await reader.next()
|
||||
try:
|
||||
with tar_file.open("wb") as backup:
|
||||
while True:
|
||||
chunk = await contents.read_chunk()
|
||||
if not chunk:
|
||||
break
|
||||
backup.write(chunk)
|
||||
|
||||
except OSError as err:
|
||||
if err.errno == errno.EBADMSG and location in {
|
||||
LOCATION_CLOUD_BACKUP,
|
||||
None,
|
||||
}:
|
||||
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
|
||||
_LOGGER.error("Can't write new backup file: %s", err)
|
||||
return False
|
||||
|
||||
except asyncio.CancelledError:
|
||||
return False
|
||||
tar_file = await self.sys_run_in_executor(open_backup_file)
|
||||
while chunk := await contents.read_chunk(size=2**16):
|
||||
await self.sys_run_in_executor(backup_file_stream.write, chunk)
|
||||
|
||||
backup = await asyncio.shield(
|
||||
self.sys_backups.import_backup(
|
||||
@ -550,6 +550,21 @@ class APIBackups(CoreSysAttributes):
|
||||
additional_locations=locations,
|
||||
)
|
||||
)
|
||||
except OSError as err:
|
||||
if err.errno == errno.EBADMSG and location in {
|
||||
LOCATION_CLOUD_BACKUP,
|
||||
None,
|
||||
}:
|
||||
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
|
||||
_LOGGER.error("Can't write new backup file: %s", err)
|
||||
return False
|
||||
|
||||
except asyncio.CancelledError:
|
||||
return False
|
||||
|
||||
finally:
|
||||
if temp_dir or backup:
|
||||
await self.sys_run_in_executor(close_backup_file)
|
||||
|
||||
if backup:
|
||||
return {ATTR_SLUG: backup.slug}
|
||||
|
@ -158,25 +158,35 @@ class Supervisor(CoreSysAttributes):
|
||||
) from err
|
||||
|
||||
# Load
|
||||
with TemporaryDirectory(dir=self.sys_config.path_tmp) as tmp_dir:
|
||||
profile_file = Path(tmp_dir, "apparmor.txt")
|
||||
try:
|
||||
profile_file.write_text(data, encoding="utf-8")
|
||||
except OSError as err:
|
||||
if err.errno == errno.EBADMSG:
|
||||
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
|
||||
raise SupervisorAppArmorError(
|
||||
f"Can't write temporary profile: {err!s}", _LOGGER.error
|
||||
) from err
|
||||
temp_dir: TemporaryDirectory | None = None
|
||||
|
||||
try:
|
||||
await self.sys_host.apparmor.load_profile(
|
||||
"hassio-supervisor", profile_file
|
||||
)
|
||||
except HostAppArmorError as err:
|
||||
raise SupervisorAppArmorError(
|
||||
"Can't update AppArmor profile!", _LOGGER.error
|
||||
) from err
|
||||
def write_profile() -> Path:
|
||||
nonlocal temp_dir
|
||||
temp_dir = TemporaryDirectory(dir=self.sys_config.path_tmp)
|
||||
profile_file = Path(temp_dir.name, "apparmor.txt")
|
||||
profile_file.write_text(data, encoding="utf-8")
|
||||
return profile_file
|
||||
|
||||
try:
|
||||
profile_file = await self.sys_run_in_executor(write_profile)
|
||||
|
||||
await self.sys_host.apparmor.load_profile("hassio-supervisor", profile_file)
|
||||
|
||||
except OSError as err:
|
||||
if err.errno == errno.EBADMSG:
|
||||
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
|
||||
raise SupervisorAppArmorError(
|
||||
f"Can't write temporary profile: {err!s}", _LOGGER.error
|
||||
) from err
|
||||
|
||||
except HostAppArmorError as err:
|
||||
raise SupervisorAppArmorError(
|
||||
"Can't update AppArmor profile!", _LOGGER.error
|
||||
) from err
|
||||
|
||||
finally:
|
||||
if temp_dir:
|
||||
await self.sys_run_in_executor(temp_dir.cleanup)
|
||||
|
||||
async def update(self, version: AwesomeVersion | None = None) -> None:
|
||||
"""Update Supervisor version."""
|
||||
|
@ -90,6 +90,7 @@ def remove_folder(
|
||||
Is needed to avoid issue with:
|
||||
- CAP_DAC_OVERRIDE
|
||||
- CAP_DAC_READ_SEARCH
|
||||
Must be run in executor.
|
||||
"""
|
||||
find_args = []
|
||||
if content_only:
|
||||
@ -114,7 +115,10 @@ def remove_folder_with_excludes(
|
||||
excludes: list[str],
|
||||
tmp_dir: Path | None = None,
|
||||
) -> None:
|
||||
"""Remove folder with excludes."""
|
||||
"""Remove folder with excludes.
|
||||
|
||||
Must be run in executor.
|
||||
"""
|
||||
with TemporaryDirectory(dir=tmp_dir) as temp_path:
|
||||
temp_path = Path(temp_path)
|
||||
moved_files: list[Path] = []
|
||||
|
Loading…
x
Reference in New Issue
Block a user