mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-10-30 14:09:47 +00:00
Compare commits
6 Commits
avoid-addi
...
reject-cor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d9d33c9fa | ||
|
|
e4959b4f10 | ||
|
|
78353220de | ||
|
|
131cc3b6d1 | ||
|
|
b92f5976a3 | ||
|
|
370c961c9e |
9
.github/workflows/builder.yml
vendored
9
.github/workflows/builder.yml
vendored
@@ -320,6 +320,15 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Wait for Home Assistant Core to start
|
||||
run: |
|
||||
echo "Waiting for Home Assistant Core to start"
|
||||
timeout 10m ha supervisor logs -f -n 10000 -b 0 | grep -q "Detect a running Home Assistant instance"
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Home Assistant Core did not start within 10 minutes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create full backup
|
||||
id: backup
|
||||
run: |
|
||||
|
||||
@@ -8,7 +8,7 @@ pytest-asyncio==0.25.2
|
||||
pytest-cov==7.0.0
|
||||
pytest-timeout==2.4.0
|
||||
pytest==8.4.2
|
||||
ruff==0.14.1
|
||||
ruff==0.14.2
|
||||
time-machine==2.19.0
|
||||
types-docker==7.1.0.20251009
|
||||
types-pyyaml==6.0.12.20250915
|
||||
|
||||
@@ -253,16 +253,6 @@ class APIIngress(CoreSysAttributes):
|
||||
skip_auto_headers={hdrs.CONTENT_TYPE},
|
||||
) as result:
|
||||
headers = _response_header(result)
|
||||
|
||||
# Empty body responses (304, 204, HEAD, etc.) should not be streamed,
|
||||
# otherwise aiohttp < 3.9.0 may generate an invalid "0\r\n\r\n" chunk
|
||||
# This also avoids setting content_type for empty responses.
|
||||
if must_be_empty_body(request.method, result.status):
|
||||
return web.Response(
|
||||
headers=headers,
|
||||
status=result.status,
|
||||
)
|
||||
|
||||
# Avoid parsing content_type in simple cases for better performance
|
||||
if maybe_content_type := result.headers.get(hdrs.CONTENT_TYPE):
|
||||
content_type = (maybe_content_type.partition(";"))[0].strip()
|
||||
@@ -270,7 +260,11 @@ class APIIngress(CoreSysAttributes):
|
||||
content_type = result.content_type
|
||||
# Simple request
|
||||
if (
|
||||
hdrs.CONTENT_LENGTH in result.headers
|
||||
# empty body responses should not be streamed,
|
||||
# otherwise aiohttp < 3.9.0 may generate
|
||||
# an invalid "0\r\n\r\n" chunk instead of an empty response.
|
||||
must_be_empty_body(request.method, result.status)
|
||||
or hdrs.CONTENT_LENGTH in result.headers
|
||||
and int(result.headers.get(hdrs.CONTENT_LENGTH, 0)) < 4_194_000
|
||||
):
|
||||
# Return Response
|
||||
|
||||
@@ -306,6 +306,8 @@ class DockerInterface(JobGroup, ABC):
|
||||
# Our filters have all passed. Time to update the job
|
||||
# Only downloading and extracting have progress details. Use that to set extra
|
||||
# We'll leave it around on later stages as the total bytes may be useful after that stage
|
||||
# Enforce range to prevent float drift error
|
||||
progress = max(0, min(progress, 100))
|
||||
if (
|
||||
stage in {PullImageLayerStage.DOWNLOADING, PullImageLayerStage.EXTRACTING}
|
||||
and reference.progress_detail
|
||||
@@ -371,7 +373,7 @@ class DockerInterface(JobGroup, ABC):
|
||||
|
||||
# To reduce noise, limit updates to when result has changed by an entire percent or when stage changed
|
||||
if stage != install_job.stage or progress >= install_job.progress + 1:
|
||||
install_job.update(stage=stage.status, progress=progress)
|
||||
install_job.update(stage=stage.status, progress=max(0, min(progress, 100)))
|
||||
|
||||
@Job(
|
||||
name="docker_interface_install",
|
||||
|
||||
@@ -9,7 +9,12 @@ from typing import Any
|
||||
from supervisor.resolution.const import UnhealthyReason
|
||||
|
||||
from ..coresys import CoreSys, CoreSysAttributes
|
||||
from ..exceptions import DBusError, DBusObjectError, HardwareNotFound
|
||||
from ..exceptions import (
|
||||
DBusError,
|
||||
DBusNotConnectedError,
|
||||
DBusObjectError,
|
||||
HardwareNotFound,
|
||||
)
|
||||
from .const import UdevSubsystem
|
||||
from .data import Device
|
||||
|
||||
@@ -207,6 +212,8 @@ class HwDisk(CoreSysAttributes):
|
||||
try:
|
||||
block_device = self.sys_dbus.udisks2.get_block_device_by_path(device_path)
|
||||
drive = self.sys_dbus.udisks2.get_drive(block_device.drive)
|
||||
except DBusNotConnectedError:
|
||||
return None
|
||||
except DBusObjectError:
|
||||
_LOGGER.warning(
|
||||
"Unable to find UDisks2 drive for device at %s", device_path.as_posix()
|
||||
|
||||
@@ -371,6 +371,12 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
|
||||
_LOGGER.error,
|
||||
) from err
|
||||
|
||||
if not resp:
|
||||
raise HomeAssistantBackupError(
|
||||
"Preparing backup of Home Assistant Core failed. No response from HA Core.",
|
||||
_LOGGER.error,
|
||||
)
|
||||
|
||||
if resp and not resp.get(ATTR_SUCCESS):
|
||||
raise HomeAssistantBackupError(
|
||||
f"Preparing backup of Home Assistant Core failed due to: {resp.get(ATTR_ERROR, {}).get(ATTR_MESSAGE, '')}. Check HA Core logs.",
|
||||
|
||||
@@ -225,6 +225,10 @@ class HomeAssistantWebSocket(CoreSysAttributes):
|
||||
# since it makes a new socket connection and we already have one.
|
||||
if not connected and not await self.sys_homeassistant.api.check_api_state():
|
||||
# No core access, don't try.
|
||||
_LOGGER.debug(
|
||||
"Home Assistant API is not accessible. Not sending WS message: %s",
|
||||
message,
|
||||
)
|
||||
return False
|
||||
|
||||
if not self._client:
|
||||
|
||||
@@ -376,3 +376,14 @@ async def test_try_get_nvme_life_time_missing_percent_used(
|
||||
coresys.config.path_supervisor
|
||||
)
|
||||
assert lifetime is None
|
||||
|
||||
|
||||
async def test_try_get_nvme_life_time_dbus_not_connected(coresys: CoreSys):
|
||||
"""Test getting lifetime info from an NVMe when DBUS is not connected."""
|
||||
# Set the dbus for udisks2 bus to be None, to make it forcibly disconnected.
|
||||
coresys.dbus.udisks2.dbus = None
|
||||
|
||||
lifetime = await coresys.hardware.disk.get_disk_life_time(
|
||||
coresys.config.path_supervisor
|
||||
)
|
||||
assert lifetime is None
|
||||
|
||||
Reference in New Issue
Block a user