mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-11-26 02:58:16 +00:00
Compare commits
1 Commits
main
...
handle-sup
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbb4eab381 |
56
.github/workflows/builder.yml
vendored
56
.github/workflows/builder.yml
vendored
@@ -34,9 +34,6 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
DEFAULT_PYTHON: "3.13"
|
DEFAULT_PYTHON: "3.13"
|
||||||
COSIGN_VERSION: "v2.5.3"
|
|
||||||
CRANE_VERSION: "v0.20.7"
|
|
||||||
CRANE_SHA256: "8ef3564d264e6b5ca93f7b7f5652704c4dd29d33935aff6947dd5adefd05953e"
|
|
||||||
BUILD_NAME: supervisor
|
BUILD_NAME: supervisor
|
||||||
BUILD_TYPE: supervisor
|
BUILD_TYPE: supervisor
|
||||||
|
|
||||||
@@ -129,7 +126,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
if: needs.init.outputs.publish == 'true'
|
if: needs.init.outputs.publish == 'true'
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
@@ -137,7 +134,7 @@ jobs:
|
|||||||
if: needs.init.outputs.publish == 'true'
|
if: needs.init.outputs.publish == 'true'
|
||||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||||
with:
|
with:
|
||||||
cosign-release: ${{ env.COSIGN_VERSION }}
|
cosign-release: "v2.5.3"
|
||||||
|
|
||||||
- name: Install dirhash and calc hash
|
- name: Install dirhash and calc hash
|
||||||
if: needs.init.outputs.publish == 'true'
|
if: needs.init.outputs.publish == 'true'
|
||||||
@@ -176,7 +173,7 @@ jobs:
|
|||||||
|
|
||||||
version:
|
version:
|
||||||
name: Update version
|
name: Update version
|
||||||
needs: ["init", "run_supervisor", "retag_deprecated"]
|
needs: ["init", "run_supervisor"]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
@@ -355,50 +352,3 @@ jobs:
|
|||||||
- name: Get supervisor logs on failiure
|
- name: Get supervisor logs on failiure
|
||||||
if: ${{ cancelled() || failure() }}
|
if: ${{ cancelled() || failure() }}
|
||||||
run: docker logs hassio_supervisor
|
run: docker logs hassio_supervisor
|
||||||
|
|
||||||
retag_deprecated:
|
|
||||||
needs: ["build", "init"]
|
|
||||||
name: Re-tag deprecated ${{ matrix.arch }} images
|
|
||||||
if: needs.init.outputs.publish == 'true'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
id-token: write
|
|
||||||
packages: write
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: ["armhf", "armv7", "i386"]
|
|
||||||
env:
|
|
||||||
# Last available release for deprecated architectures
|
|
||||||
FROZEN_VERSION: "2025.11.5"
|
|
||||||
steps:
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install Cosign
|
|
||||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
|
||||||
with:
|
|
||||||
cosign-release: ${{ env.COSIGN_VERSION }}
|
|
||||||
|
|
||||||
- name: Install crane
|
|
||||||
run: |
|
|
||||||
curl -sLO https://github.com/google/go-containerregistry/releases/download/${{ env.CRANE_VERSION }}/go-containerregistry_Linux_x86_64.tar.gz
|
|
||||||
echo "${{ env.CRANE_SHA256 }} go-containerregistry_Linux_x86_64.tar.gz" | sha256sum -c -
|
|
||||||
tar xzf go-containerregistry_Linux_x86_64.tar.gz crane
|
|
||||||
sudo mv crane /usr/local/bin/
|
|
||||||
|
|
||||||
- name: Re-tag deprecated image with updated version label
|
|
||||||
run: |
|
|
||||||
crane auth login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
crane mutate \
|
|
||||||
--label io.hass.version=${{ needs.init.outputs.version }} \
|
|
||||||
--tag ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ needs.init.outputs.version }} \
|
|
||||||
ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ env.FROZEN_VERSION }}
|
|
||||||
|
|
||||||
- name: Sign image with Cosign
|
|
||||||
run: |
|
|
||||||
cosign sign --yes ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ needs.init.outputs.version }}
|
|
||||||
|
|||||||
18
.github/workflows/ci.yaml
vendored
18
.github/workflows/ci.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
id: python
|
id: python
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore Python virtual environment
|
- name: Restore Python virtual environment
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -171,7 +171,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -215,7 +215,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -259,7 +259,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -295,7 +295,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -341,7 +341,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
@@ -400,7 +400,7 @@ jobs:
|
|||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
|
||||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ needs.prepare.outputs.python-version }}
|
python-version: ${{ needs.prepare.outputs.python-version }}
|
||||||
|
|||||||
2
.github/workflows/update_frontend.yml
vendored
2
.github/workflows/update_frontend.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
rm -f supervisor/api/panel/home_assistant_frontend_supervisor-*.tar.gz
|
rm -f supervisor/api/panel/home_assistant_frontend_supervisor-*.tar.gz
|
||||||
- name: Create PR
|
- name: Create PR
|
||||||
uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9
|
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||||
with:
|
with:
|
||||||
commit-message: "Update frontend to version ${{ needs.check-version.outputs.latest_version }}"
|
commit-message: "Update frontend to version ${{ needs.check-version.outputs.latest_version }}"
|
||||||
branch: autoupdate-frontend
|
branch: autoupdate-frontend
|
||||||
|
|||||||
10
build.yaml
10
build.yaml
@@ -1,7 +1,13 @@
|
|||||||
image: ghcr.io/home-assistant/{arch}-hassio-supervisor
|
image: ghcr.io/home-assistant/{arch}-hassio-supervisor
|
||||||
build_from:
|
build_from:
|
||||||
aarch64: ghcr.io/home-assistant/aarch64-base-python:3.13-alpine3.22-2025.11.1
|
aarch64: ghcr.io/home-assistant/aarch64-base-python:3.13-alpine3.22
|
||||||
amd64: ghcr.io/home-assistant/amd64-base-python:3.13-alpine3.22-2025.11.1
|
armhf: ghcr.io/home-assistant/armhf-base-python:3.13-alpine3.22
|
||||||
|
armv7: ghcr.io/home-assistant/armv7-base-python:3.13-alpine3.22
|
||||||
|
amd64: ghcr.io/home-assistant/amd64-base-python:3.13-alpine3.22
|
||||||
|
i386: ghcr.io/home-assistant/i386-base-python:3.13-alpine3.22
|
||||||
|
codenotary:
|
||||||
|
signer: notary@home-assistant.io
|
||||||
|
base_image: notary@home-assistant.io
|
||||||
cosign:
|
cosign:
|
||||||
base_identity: https://github.com/home-assistant/docker-base/.*
|
base_identity: https://github.com/home-assistant/docker-base/.*
|
||||||
identity: https://github.com/home-assistant/supervisor/.*
|
identity: https://github.com/home-assistant/supervisor/.*
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ aiohttp==3.13.2
|
|||||||
atomicwrites-homeassistant==1.4.1
|
atomicwrites-homeassistant==1.4.1
|
||||||
attrs==25.4.0
|
attrs==25.4.0
|
||||||
awesomeversion==25.8.0
|
awesomeversion==25.8.0
|
||||||
backports.zstd==1.1.0
|
backports.zstd==1.0.0
|
||||||
blockbuster==1.5.25
|
blockbuster==1.5.25
|
||||||
brotli==1.2.0
|
brotli==1.2.0
|
||||||
ciso8601==2.3.3
|
ciso8601==2.3.3
|
||||||
@@ -25,8 +25,8 @@ pyudev==0.24.4
|
|||||||
PyYAML==6.0.3
|
PyYAML==6.0.3
|
||||||
requests==2.32.5
|
requests==2.32.5
|
||||||
securetar==2025.2.1
|
securetar==2025.2.1
|
||||||
sentry-sdk==2.46.0
|
sentry-sdk==2.45.0
|
||||||
setuptools==80.9.0
|
setuptools==80.9.0
|
||||||
voluptuous==0.15.2
|
voluptuous==0.15.2
|
||||||
dbus-fast==3.1.2
|
dbus-fast==2.45.1
|
||||||
zlib-fast==0.2.1
|
zlib-fast==0.2.1
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
astroid==4.0.2
|
astroid==4.0.2
|
||||||
coverage==7.12.0
|
coverage==7.12.0
|
||||||
mypy==1.18.2
|
mypy==1.18.2
|
||||||
pre-commit==4.5.0
|
pre-commit==4.4.0
|
||||||
pylint==4.0.3
|
pylint==4.0.3
|
||||||
pytest-aiohttp==1.1.0
|
pytest-aiohttp==1.1.0
|
||||||
pytest-asyncio==1.3.0
|
pytest-asyncio==1.3.0
|
||||||
pytest-cov==7.0.0
|
pytest-cov==7.0.0
|
||||||
pytest-timeout==2.4.0
|
pytest-timeout==2.4.0
|
||||||
pytest==9.0.1
|
pytest==9.0.1
|
||||||
ruff==0.14.6
|
ruff==0.14.5
|
||||||
time-machine==3.1.0
|
time-machine==3.0.0
|
||||||
types-docker==7.1.0.20251125
|
types-docker==7.1.0.20251009
|
||||||
types-pyyaml==6.0.12.20250915
|
types-pyyaml==6.0.12.20250915
|
||||||
types-requests==2.32.4.20250913
|
types-requests==2.32.4.20250913
|
||||||
urllib3==2.5.0
|
urllib3==2.5.0
|
||||||
|
|||||||
@@ -343,14 +343,10 @@ class APIHost(CoreSysAttributes):
|
|||||||
|
|
||||||
disk = self.sys_hardware.disk
|
disk = self.sys_hardware.disk
|
||||||
|
|
||||||
total, _, free = await self.sys_run_in_executor(
|
total, used, _ = await self.sys_run_in_executor(
|
||||||
disk.disk_usage, self.sys_config.path_supervisor
|
disk.disk_usage, self.sys_config.path_supervisor
|
||||||
)
|
)
|
||||||
|
|
||||||
# Calculate used by subtracting free makes sure we include reserved space
|
|
||||||
# in used space reporting.
|
|
||||||
used = total - free
|
|
||||||
|
|
||||||
known_paths = await self.sys_run_in_executor(
|
known_paths = await self.sys_run_in_executor(
|
||||||
disk.get_dir_sizes,
|
disk.get_dir_sizes,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,10 +63,12 @@ def json_loads(data: Any) -> dict[str, Any]:
|
|||||||
def api_process(method):
|
def api_process(method):
|
||||||
"""Wrap function with true/false calls to rest api."""
|
"""Wrap function with true/false calls to rest api."""
|
||||||
|
|
||||||
async def wrap_api(*args, **kwargs) -> web.Response | web.StreamResponse:
|
async def wrap_api(
|
||||||
|
api: CoreSysAttributes, *args, **kwargs
|
||||||
|
) -> web.Response | web.StreamResponse:
|
||||||
"""Return API information."""
|
"""Return API information."""
|
||||||
try:
|
try:
|
||||||
answer = await method(*args, **kwargs)
|
answer = await method(api, *args, **kwargs)
|
||||||
except BackupFileNotFoundError as err:
|
except BackupFileNotFoundError as err:
|
||||||
return api_return_error(err, status=404)
|
return api_return_error(err, status=404)
|
||||||
except APIError as err:
|
except APIError as err:
|
||||||
@@ -107,10 +109,12 @@ def api_process_raw(content, *, error_type=None):
|
|||||||
def wrap_method(method):
|
def wrap_method(method):
|
||||||
"""Wrap function with raw output to rest api."""
|
"""Wrap function with raw output to rest api."""
|
||||||
|
|
||||||
async def wrap_api(*args, **kwargs) -> web.Response | web.StreamResponse:
|
async def wrap_api(
|
||||||
|
api: CoreSysAttributes, *args, **kwargs
|
||||||
|
) -> web.Response | web.StreamResponse:
|
||||||
"""Return api information."""
|
"""Return api information."""
|
||||||
try:
|
try:
|
||||||
msg_data = await method(*args, **kwargs)
|
msg_data = await method(api, *args, **kwargs)
|
||||||
except APIError as err:
|
except APIError as err:
|
||||||
return api_return_error(
|
return api_return_error(
|
||||||
err,
|
err,
|
||||||
|
|||||||
@@ -306,8 +306,6 @@ class DeviceType(IntEnum):
|
|||||||
VLAN = 11
|
VLAN = 11
|
||||||
TUN = 16
|
TUN = 16
|
||||||
VETH = 20
|
VETH = 20
|
||||||
WIREGUARD = 29
|
|
||||||
LOOPBACK = 32
|
|
||||||
|
|
||||||
|
|
||||||
class WirelessMethodType(IntEnum):
|
class WirelessMethodType(IntEnum):
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class DBusManager(CoreSysAttributes):
|
|||||||
|
|
||||||
async def load(self) -> None:
|
async def load(self) -> None:
|
||||||
"""Connect interfaces to D-Bus."""
|
"""Connect interfaces to D-Bus."""
|
||||||
if not await self.sys_run_in_executor(SOCKET_DBUS.exists):
|
if not SOCKET_DBUS.exists():
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"No D-Bus support on Host. Disabled any kind of host control!"
|
"No D-Bus support on Host. Disabled any kind of host control!"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -134,10 +134,9 @@ class NetworkManager(DBusInterfaceProxy):
|
|||||||
async def check_connectivity(self, *, force: bool = False) -> ConnectivityState:
|
async def check_connectivity(self, *, force: bool = False) -> ConnectivityState:
|
||||||
"""Check the connectivity of the host."""
|
"""Check the connectivity of the host."""
|
||||||
if force:
|
if force:
|
||||||
return ConnectivityState(
|
return await self.connected_dbus.call("check_connectivity")
|
||||||
await self.connected_dbus.call("check_connectivity")
|
else:
|
||||||
)
|
return await self.connected_dbus.get("connectivity")
|
||||||
return ConnectivityState(await self.connected_dbus.get("connectivity"))
|
|
||||||
|
|
||||||
async def connect(self, bus: MessageBus) -> None:
|
async def connect(self, bus: MessageBus) -> None:
|
||||||
"""Connect to system's D-Bus."""
|
"""Connect to system's D-Bus."""
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class NetworkConnection(DBusInterfaceProxy):
|
|||||||
@dbus_property
|
@dbus_property
|
||||||
def state(self) -> ConnectionStateType:
|
def state(self) -> ConnectionStateType:
|
||||||
"""Return the state of the connection."""
|
"""Return the state of the connection."""
|
||||||
return ConnectionStateType(self.properties[DBUS_ATTR_STATE])
|
return self.properties[DBUS_ATTR_STATE]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_flags(self) -> set[ConnectionStateFlags]:
|
def state_flags(self) -> set[ConnectionStateFlags]:
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"""NetworkInterface object for Network Manager."""
|
"""NetworkInterface object for Network Manager."""
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from dbus_fast.aio.message_bus import MessageBus
|
from dbus_fast.aio.message_bus import MessageBus
|
||||||
@@ -24,8 +23,6 @@ from .connection import NetworkConnection
|
|||||||
from .setting import NetworkSetting
|
from .setting import NetworkSetting
|
||||||
from .wireless import NetworkWireless
|
from .wireless import NetworkWireless
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkInterface(DBusInterfaceProxy):
|
class NetworkInterface(DBusInterfaceProxy):
|
||||||
"""NetworkInterface object represents Network Manager Device objects.
|
"""NetworkInterface object represents Network Manager Device objects.
|
||||||
@@ -60,15 +57,7 @@ class NetworkInterface(DBusInterfaceProxy):
|
|||||||
@dbus_property
|
@dbus_property
|
||||||
def type(self) -> DeviceType:
|
def type(self) -> DeviceType:
|
||||||
"""Return interface type."""
|
"""Return interface type."""
|
||||||
try:
|
return self.properties[DBUS_ATTR_DEVICE_TYPE]
|
||||||
return DeviceType(self.properties[DBUS_ATTR_DEVICE_TYPE])
|
|
||||||
except ValueError:
|
|
||||||
_LOGGER.debug(
|
|
||||||
"Unknown device type %s for %s, treating as UNKNOWN",
|
|
||||||
self.properties[DBUS_ATTR_DEVICE_TYPE],
|
|
||||||
self.object_path,
|
|
||||||
)
|
|
||||||
return DeviceType.UNKNOWN
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@dbus_property
|
@dbus_property
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class Resolved(DBusInterfaceProxy):
|
|||||||
@dbus_property
|
@dbus_property
|
||||||
def current_dns_server(
|
def current_dns_server(
|
||||||
self,
|
self,
|
||||||
) -> tuple[int, DNSAddressFamily, bytes] | None:
|
) -> list[tuple[int, DNSAddressFamily, bytes]] | None:
|
||||||
"""Return current DNS server."""
|
"""Return current DNS server."""
|
||||||
return self.properties[DBUS_ATTR_CURRENT_DNS_SERVER]
|
return self.properties[DBUS_ATTR_CURRENT_DNS_SERVER]
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class Resolved(DBusInterfaceProxy):
|
|||||||
@dbus_property
|
@dbus_property
|
||||||
def current_dns_server_ex(
|
def current_dns_server_ex(
|
||||||
self,
|
self,
|
||||||
) -> tuple[int, DNSAddressFamily, bytes, int, str] | None:
|
) -> list[tuple[int, DNSAddressFamily, bytes, int, str]] | None:
|
||||||
"""Return current DNS server including port and server name."""
|
"""Return current DNS server including port and server name."""
|
||||||
return self.properties[DBUS_ATTR_CURRENT_DNS_SERVER_EX]
|
return self.properties[DBUS_ATTR_CURRENT_DNS_SERVER_EX]
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class SystemdUnit(DBusInterface):
|
|||||||
@dbus_connected
|
@dbus_connected
|
||||||
async def get_active_state(self) -> UnitActiveState:
|
async def get_active_state(self) -> UnitActiveState:
|
||||||
"""Get active state of the unit."""
|
"""Get active state of the unit."""
|
||||||
return UnitActiveState(await self.connected_dbus.Unit.get("active_state"))
|
return await self.connected_dbus.Unit.get("active_state")
|
||||||
|
|
||||||
@dbus_connected
|
@dbus_connected
|
||||||
def properties_changed(self) -> DBusSignalWrapper:
|
def properties_changed(self) -> DBusSignalWrapper:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from dbus_fast import Variant
|
|||||||
from .const import EncryptType, EraseMode
|
from .const import EncryptType, EraseMode
|
||||||
|
|
||||||
|
|
||||||
def udisks2_bytes_to_path(path_bytes: bytes) -> Path:
|
def udisks2_bytes_to_path(path_bytes: bytearray) -> Path:
|
||||||
"""Convert bytes to path object without null character on end."""
|
"""Convert bytes to path object without null character on end."""
|
||||||
if path_bytes and path_bytes[-1] == 0:
|
if path_bytes and path_bytes[-1] == 0:
|
||||||
return Path(path_bytes[:-1].decode())
|
return Path(path_bytes[:-1].decode())
|
||||||
@@ -73,7 +73,7 @@ FormatOptionsDataType = TypedDict(
|
|||||||
{
|
{
|
||||||
"label": NotRequired[str],
|
"label": NotRequired[str],
|
||||||
"take-ownership": NotRequired[bool],
|
"take-ownership": NotRequired[bool],
|
||||||
"encrypt.passphrase": NotRequired[bytes],
|
"encrypt.passphrase": NotRequired[bytearray],
|
||||||
"encrypt.type": NotRequired[str],
|
"encrypt.type": NotRequired[str],
|
||||||
"erase": NotRequired[str],
|
"erase": NotRequired[str],
|
||||||
"update-partition-type": NotRequired[bool],
|
"update-partition-type": NotRequired[bool],
|
||||||
|
|||||||
@@ -76,25 +76,15 @@ class DockerInfo:
|
|||||||
storage: str = attr.ib()
|
storage: str = attr.ib()
|
||||||
logging: str = attr.ib()
|
logging: str = attr.ib()
|
||||||
cgroup: str = attr.ib()
|
cgroup: str = attr.ib()
|
||||||
support_cpu_realtime: bool = attr.ib()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def new(data: dict[str, Any]) -> DockerInfo:
|
def new(data: dict[str, Any]):
|
||||||
"""Create a object from docker info."""
|
"""Create a object from docker info."""
|
||||||
# Check if CONFIG_RT_GROUP_SCHED is loaded (blocking I/O in executor)
|
|
||||||
cpu_rt_file_exists = await asyncio.get_running_loop().run_in_executor(
|
|
||||||
None, Path("/sys/fs/cgroup/cpu/cpu.rt_runtime_us").exists
|
|
||||||
)
|
|
||||||
cpu_rt_supported = (
|
|
||||||
cpu_rt_file_exists and os.environ.get(ENV_SUPERVISOR_CPU_RT) == "1"
|
|
||||||
)
|
|
||||||
|
|
||||||
return DockerInfo(
|
return DockerInfo(
|
||||||
AwesomeVersion(data.get("ServerVersion", "0.0.0")),
|
AwesomeVersion(data.get("ServerVersion", "0.0.0")),
|
||||||
data.get("Driver", "unknown"),
|
data.get("Driver", "unknown"),
|
||||||
data.get("LoggingDriver", "unknown"),
|
data.get("LoggingDriver", "unknown"),
|
||||||
data.get("CgroupVersion", "1"),
|
data.get("CgroupVersion", "1"),
|
||||||
cpu_rt_supported,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -105,6 +95,13 @@ class DockerInfo:
|
|||||||
except AwesomeVersionCompareException:
|
except AwesomeVersionCompareException:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def support_cpu_realtime(self) -> bool:
|
||||||
|
"""Return true, if CONFIG_RT_GROUP_SCHED is loaded."""
|
||||||
|
if not Path("/sys/fs/cgroup/cpu/cpu.rt_runtime_us").exists():
|
||||||
|
return False
|
||||||
|
return bool(os.environ.get(ENV_SUPERVISOR_CPU_RT) == "1")
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, slots=True)
|
@dataclass(frozen=True, slots=True)
|
||||||
class PullProgressDetail:
|
class PullProgressDetail:
|
||||||
@@ -237,7 +234,7 @@ class DockerAPI(CoreSysAttributes):
|
|||||||
timeout=900,
|
timeout=900,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self._info = await DockerInfo.new(self.dockerpy.info())
|
self._info = DockerInfo.new(self.dockerpy.info())
|
||||||
await self.config.read_data()
|
await self.config.read_data()
|
||||||
self._network = await DockerNetwork(self.dockerpy).post_init(
|
self._network = await DockerNetwork(self.dockerpy).post_init(
|
||||||
self.config.enable_ipv6, self.config.mtu
|
self.config.enable_ipv6, self.config.mtu
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ class JobCondition(StrEnum):
|
|||||||
PLUGINS_UPDATED = "plugins_updated"
|
PLUGINS_UPDATED = "plugins_updated"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
SUPERVISOR_UPDATED = "supervisor_updated"
|
SUPERVISOR_UPDATED = "supervisor_updated"
|
||||||
ARCHITECTURE_SUPPORTED = "architecture_supported"
|
|
||||||
|
|
||||||
|
|
||||||
class JobConcurrency(StrEnum):
|
class JobConcurrency(StrEnum):
|
||||||
|
|||||||
@@ -441,14 +441,6 @@ class Job(CoreSysAttributes):
|
|||||||
raise JobConditionException(
|
raise JobConditionException(
|
||||||
f"'{method_name}' blocked from execution, supervisor needs to be updated first"
|
f"'{method_name}' blocked from execution, supervisor needs to be updated first"
|
||||||
)
|
)
|
||||||
if (
|
|
||||||
JobCondition.ARCHITECTURE_SUPPORTED in used_conditions
|
|
||||||
and UnsupportedReason.SYSTEM_ARCHITECTURE
|
|
||||||
in coresys.sys_resolution.unsupported
|
|
||||||
):
|
|
||||||
raise JobConditionException(
|
|
||||||
f"'{method_name}' blocked from execution, unsupported system architecture"
|
|
||||||
)
|
|
||||||
|
|
||||||
if JobCondition.PLUGINS_UPDATED in used_conditions and (
|
if JobCondition.PLUGINS_UPDATED in used_conditions and (
|
||||||
out_of_date := [
|
out_of_date := [
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"""A collection of tasks."""
|
"""A collection of tasks."""
|
||||||
|
|
||||||
|
from contextlib import suppress
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
@@ -13,6 +14,7 @@ from ..exceptions import (
|
|||||||
BackupFileNotFoundError,
|
BackupFileNotFoundError,
|
||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
ObserverError,
|
ObserverError,
|
||||||
|
SupervisorUpdateError,
|
||||||
)
|
)
|
||||||
from ..homeassistant.const import LANDINGPAGE, WSType
|
from ..homeassistant.const import LANDINGPAGE, WSType
|
||||||
from ..jobs.const import JobConcurrency
|
from ..jobs.const import JobConcurrency
|
||||||
@@ -161,7 +163,6 @@ class Tasks(CoreSysAttributes):
|
|||||||
JobCondition.INTERNET_HOST,
|
JobCondition.INTERNET_HOST,
|
||||||
JobCondition.OS_SUPPORTED,
|
JobCondition.OS_SUPPORTED,
|
||||||
JobCondition.RUNNING,
|
JobCondition.RUNNING,
|
||||||
JobCondition.ARCHITECTURE_SUPPORTED,
|
|
||||||
],
|
],
|
||||||
concurrency=JobConcurrency.REJECT,
|
concurrency=JobConcurrency.REJECT,
|
||||||
)
|
)
|
||||||
@@ -174,6 +175,10 @@ class Tasks(CoreSysAttributes):
|
|||||||
"Found new Supervisor version %s, updating",
|
"Found new Supervisor version %s, updating",
|
||||||
self.sys_supervisor.latest_version,
|
self.sys_supervisor.latest_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Errors are logged by the exceptions, we can't really do something
|
||||||
|
# if an update fails here.
|
||||||
|
with suppress(SupervisorUpdateError):
|
||||||
await self.sys_supervisor.update()
|
await self.sys_supervisor.update()
|
||||||
|
|
||||||
async def _watchdog_homeassistant_api(self):
|
async def _watchdog_homeassistant_api(self):
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class Mount(CoreSysAttributes, ABC):
|
|||||||
@property
|
@property
|
||||||
def state(self) -> UnitActiveState | None:
|
def state(self) -> UnitActiveState | None:
|
||||||
"""Get state of mount."""
|
"""Get state of mount."""
|
||||||
return UnitActiveState(self._state) if self._state is not None else None
|
return self._state
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def local_where(self) -> Path:
|
def local_where(self) -> Path:
|
||||||
|
|||||||
@@ -23,5 +23,4 @@ PLUGIN_UPDATE_CONDITIONS = [
|
|||||||
JobCondition.HEALTHY,
|
JobCondition.HEALTHY,
|
||||||
JobCondition.INTERNET_HOST,
|
JobCondition.INTERNET_HOST,
|
||||||
JobCondition.SUPERVISOR_UPDATED,
|
JobCondition.SUPERVISOR_UPDATED,
|
||||||
JobCondition.ARCHITECTURE_SUPPORTED,
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ class UnsupportedReason(StrEnum):
|
|||||||
SYSTEMD_JOURNAL = "systemd_journal"
|
SYSTEMD_JOURNAL = "systemd_journal"
|
||||||
SYSTEMD_RESOLVED = "systemd_resolved"
|
SYSTEMD_RESOLVED = "systemd_resolved"
|
||||||
VIRTUALIZATION_IMAGE = "virtualization_image"
|
VIRTUALIZATION_IMAGE = "virtualization_image"
|
||||||
SYSTEM_ARCHITECTURE = "system_architecture"
|
|
||||||
|
|
||||||
|
|
||||||
class UnhealthyReason(StrEnum):
|
class UnhealthyReason(StrEnum):
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ from ...coresys import CoreSys
|
|||||||
from ..const import UnsupportedReason
|
from ..const import UnsupportedReason
|
||||||
from .base import EvaluateBase
|
from .base import EvaluateBase
|
||||||
|
|
||||||
|
SUPPORTED_OS = ["Debian GNU/Linux 12 (bookworm)"]
|
||||||
|
|
||||||
|
|
||||||
def setup(coresys: CoreSys) -> EvaluateBase:
|
def setup(coresys: CoreSys) -> EvaluateBase:
|
||||||
"""Initialize evaluation-setup function."""
|
"""Initialize evaluation-setup function."""
|
||||||
@@ -31,4 +33,6 @@ class EvaluateOperatingSystem(EvaluateBase):
|
|||||||
|
|
||||||
async def evaluate(self) -> bool:
|
async def evaluate(self) -> bool:
|
||||||
"""Run evaluation."""
|
"""Run evaluation."""
|
||||||
return not self.sys_os.available
|
if self.sys_os.available:
|
||||||
|
return False
|
||||||
|
return self.sys_host.info.operating_system not in SUPPORTED_OS
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
"""Evaluation class for system architecture support."""
|
|
||||||
|
|
||||||
from ...const import CoreState
|
|
||||||
from ...coresys import CoreSys
|
|
||||||
from ..const import UnsupportedReason
|
|
||||||
from .base import EvaluateBase
|
|
||||||
|
|
||||||
|
|
||||||
def setup(coresys: CoreSys) -> EvaluateBase:
|
|
||||||
"""Initialize evaluation-setup function."""
|
|
||||||
return EvaluateSystemArchitecture(coresys)
|
|
||||||
|
|
||||||
|
|
||||||
class EvaluateSystemArchitecture(EvaluateBase):
|
|
||||||
"""Evaluate if the current Supervisor architecture is supported."""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def reason(self) -> UnsupportedReason:
|
|
||||||
"""Return a UnsupportedReason enum."""
|
|
||||||
return UnsupportedReason.SYSTEM_ARCHITECTURE
|
|
||||||
|
|
||||||
@property
|
|
||||||
def on_failure(self) -> str:
|
|
||||||
"""Return a string that is printed when self.evaluate is True."""
|
|
||||||
return "System architecture is no longer supported. Move to a supported system architecture."
|
|
||||||
|
|
||||||
@property
|
|
||||||
def states(self) -> list[CoreState]:
|
|
||||||
"""Return a list of valid states when this evaluation can run."""
|
|
||||||
return [CoreState.INITIALIZE]
|
|
||||||
|
|
||||||
async def evaluate(self):
|
|
||||||
"""Run evaluation."""
|
|
||||||
return self.sys_host.info.sys_arch.supervisor in {
|
|
||||||
"i386",
|
|
||||||
"armhf",
|
|
||||||
"armv7",
|
|
||||||
}
|
|
||||||
@@ -242,10 +242,9 @@ class Updater(FileConfiguration, CoreSysAttributes):
|
|||||||
@Job(
|
@Job(
|
||||||
name="updater_fetch_data",
|
name="updater_fetch_data",
|
||||||
conditions=[
|
conditions=[
|
||||||
JobCondition.ARCHITECTURE_SUPPORTED,
|
|
||||||
JobCondition.INTERNET_SYSTEM,
|
JobCondition.INTERNET_SYSTEM,
|
||||||
JobCondition.HOME_ASSISTANT_CORE_SUPPORTED,
|
|
||||||
JobCondition.OS_SUPPORTED,
|
JobCondition.OS_SUPPORTED,
|
||||||
|
JobCondition.HOME_ASSISTANT_CORE_SUPPORTED,
|
||||||
],
|
],
|
||||||
on_condition=UpdaterJobError,
|
on_condition=UpdaterJobError,
|
||||||
throttle_period=timedelta(seconds=30),
|
throttle_period=timedelta(seconds=30),
|
||||||
|
|||||||
@@ -7,7 +7,13 @@ from collections.abc import Awaitable, Callable
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Protocol, cast
|
from typing import Any, Protocol, cast
|
||||||
|
|
||||||
from dbus_fast import ErrorType, InvalidIntrospectionError, Message, MessageType
|
from dbus_fast import (
|
||||||
|
ErrorType,
|
||||||
|
InvalidIntrospectionError,
|
||||||
|
Message,
|
||||||
|
MessageType,
|
||||||
|
Variant,
|
||||||
|
)
|
||||||
from dbus_fast.aio.message_bus import MessageBus
|
from dbus_fast.aio.message_bus import MessageBus
|
||||||
from dbus_fast.aio.proxy_object import ProxyInterface, ProxyObject
|
from dbus_fast.aio.proxy_object import ProxyInterface, ProxyObject
|
||||||
from dbus_fast.errors import DBusError as DBusFastDBusError
|
from dbus_fast.errors import DBusError as DBusFastDBusError
|
||||||
@@ -259,7 +265,7 @@ class DBus:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
async def sync_property_change(
|
async def sync_property_change(
|
||||||
prop_interface: str, changed: dict[str, Any], invalidated: list[str]
|
prop_interface: str, changed: dict[str, Variant], invalidated: list[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Sync property changes to cache."""
|
"""Sync property changes to cache."""
|
||||||
if interface != prop_interface:
|
if interface != prop_interface:
|
||||||
|
|||||||
@@ -184,20 +184,3 @@ async def test_interface_becomes_unmanaged(
|
|||||||
assert wireless.is_connected is False
|
assert wireless.is_connected is False
|
||||||
assert eth0.connection is None
|
assert eth0.connection is None
|
||||||
assert connection.is_connected is False
|
assert connection.is_connected is False
|
||||||
|
|
||||||
|
|
||||||
async def test_unknown_device_type(
|
|
||||||
device_eth0_service: DeviceService, dbus_session_bus: MessageBus
|
|
||||||
):
|
|
||||||
"""Test unknown device types are handled gracefully."""
|
|
||||||
interface = NetworkInterface("/org/freedesktop/NetworkManager/Devices/1")
|
|
||||||
await interface.connect(dbus_session_bus)
|
|
||||||
|
|
||||||
# Emit an unknown device type (e.g., 1000 which doesn't exist in the enum)
|
|
||||||
device_eth0_service.emit_properties_changed({"DeviceType": 1000})
|
|
||||||
await device_eth0_service.ping()
|
|
||||||
|
|
||||||
# Should return UNKNOWN instead of crashing
|
|
||||||
assert interface.type == DeviceType.UNKNOWN
|
|
||||||
# Wireless should be None since it's not a wireless device
|
|
||||||
assert interface.wireless is None
|
|
||||||
|
|||||||
@@ -41,51 +41,51 @@ async def test_dbus_resolved_info(
|
|||||||
assert resolved.dns_over_tls == DNSOverTLSEnabled.NO
|
assert resolved.dns_over_tls == DNSOverTLSEnabled.NO
|
||||||
|
|
||||||
assert len(resolved.dns) == 2
|
assert len(resolved.dns) == 2
|
||||||
assert resolved.dns[0] == (0, 2, inet_aton("127.0.0.1"))
|
assert resolved.dns[0] == [0, 2, inet_aton("127.0.0.1")]
|
||||||
assert resolved.dns[1] == (0, 10, inet_pton(AF_INET6, "::1"))
|
assert resolved.dns[1] == [0, 10, inet_pton(AF_INET6, "::1")]
|
||||||
assert len(resolved.dns_ex) == 2
|
assert len(resolved.dns_ex) == 2
|
||||||
assert resolved.dns_ex[0] == (0, 2, inet_aton("127.0.0.1"), 0, "")
|
assert resolved.dns_ex[0] == [0, 2, inet_aton("127.0.0.1"), 0, ""]
|
||||||
assert resolved.dns_ex[1] == (0, 10, inet_pton(AF_INET6, "::1"), 0, "")
|
assert resolved.dns_ex[1] == [0, 10, inet_pton(AF_INET6, "::1"), 0, ""]
|
||||||
|
|
||||||
assert len(resolved.fallback_dns) == 2
|
assert len(resolved.fallback_dns) == 2
|
||||||
assert resolved.fallback_dns[0] == (0, 2, inet_aton("1.1.1.1"))
|
assert resolved.fallback_dns[0] == [0, 2, inet_aton("1.1.1.1")]
|
||||||
assert resolved.fallback_dns[1] == (
|
assert resolved.fallback_dns[1] == [
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
inet_pton(AF_INET6, "2606:4700:4700::1111"),
|
inet_pton(AF_INET6, "2606:4700:4700::1111"),
|
||||||
)
|
]
|
||||||
assert len(resolved.fallback_dns_ex) == 2
|
assert len(resolved.fallback_dns_ex) == 2
|
||||||
assert resolved.fallback_dns_ex[0] == (
|
assert resolved.fallback_dns_ex[0] == [
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
inet_aton("1.1.1.1"),
|
inet_aton("1.1.1.1"),
|
||||||
0,
|
0,
|
||||||
"cloudflare-dns.com",
|
"cloudflare-dns.com",
|
||||||
)
|
]
|
||||||
assert resolved.fallback_dns_ex[1] == (
|
assert resolved.fallback_dns_ex[1] == [
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
inet_pton(AF_INET6, "2606:4700:4700::1111"),
|
inet_pton(AF_INET6, "2606:4700:4700::1111"),
|
||||||
0,
|
0,
|
||||||
"cloudflare-dns.com",
|
"cloudflare-dns.com",
|
||||||
)
|
]
|
||||||
|
|
||||||
assert resolved.current_dns_server == (0, 2, inet_aton("127.0.0.1"))
|
assert resolved.current_dns_server == [0, 2, inet_aton("127.0.0.1")]
|
||||||
assert resolved.current_dns_server_ex == (
|
assert resolved.current_dns_server_ex == [
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
inet_aton("127.0.0.1"),
|
inet_aton("127.0.0.1"),
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
)
|
]
|
||||||
|
|
||||||
assert len(resolved.domains) == 1
|
assert len(resolved.domains) == 1
|
||||||
assert resolved.domains[0] == (0, "local.hass.io", False)
|
assert resolved.domains[0] == [0, "local.hass.io", False]
|
||||||
|
|
||||||
assert resolved.transaction_statistics == (0, 100000)
|
assert resolved.transaction_statistics == [0, 100000]
|
||||||
assert resolved.cache_statistics == (10, 50000, 10000)
|
assert resolved.cache_statistics == [10, 50000, 10000]
|
||||||
assert resolved.dnssec == DNSSECValidation.NO
|
assert resolved.dnssec == DNSSECValidation.NO
|
||||||
assert resolved.dnssec_statistics == (0, 0, 0, 0)
|
assert resolved.dnssec_statistics == [0, 0, 0, 0]
|
||||||
assert resolved.dnssec_supported is False
|
assert resolved.dnssec_supported is False
|
||||||
assert resolved.dnssec_negative_trust_anchors == [
|
assert resolved.dnssec_negative_trust_anchors == [
|
||||||
"168.192.in-addr.arpa",
|
"168.192.in-addr.arpa",
|
||||||
|
|||||||
@@ -185,10 +185,10 @@ async def test_start_transient_unit(
|
|||||||
"tmp-test.mount",
|
"tmp-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Description", Variant("s", "Test")),
|
["Description", Variant("s", "Test")],
|
||||||
("What", Variant("s", "//homeassistant/config")),
|
["What", Variant("s", "//homeassistant/config")],
|
||||||
("Type", Variant("s", "cifs")),
|
["Type", Variant("s", "cifs")],
|
||||||
("Options", Variant("s", "username=homeassistant,password=password")),
|
["Options", Variant("s", "username=homeassistant,password=password")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ class Resolved(DBusServiceMock):
|
|||||||
def DNS(self) -> "a(iiay)":
|
def DNS(self) -> "a(iiay)":
|
||||||
"""Get DNS."""
|
"""Get DNS."""
|
||||||
return [
|
return [
|
||||||
(0, 2, bytes([127, 0, 0, 1])),
|
[0, 2, bytes([127, 0, 0, 1])],
|
||||||
(
|
[
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
bytes(
|
bytes(
|
||||||
@@ -69,15 +69,15 @@ class Resolved(DBusServiceMock):
|
|||||||
0x1,
|
0x1,
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def DNSEx(self) -> "a(iiayqs)":
|
def DNSEx(self) -> "a(iiayqs)":
|
||||||
"""Get DNSEx."""
|
"""Get DNSEx."""
|
||||||
return [
|
return [
|
||||||
(0, 2, bytes([127, 0, 0, 1]), 0, ""),
|
[0, 2, bytes([127, 0, 0, 1]), 0, ""],
|
||||||
(
|
[
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
bytes(
|
bytes(
|
||||||
@@ -102,15 +102,15 @@ class Resolved(DBusServiceMock):
|
|||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
),
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def FallbackDNS(self) -> "a(iiay)":
|
def FallbackDNS(self) -> "a(iiay)":
|
||||||
"""Get FallbackDNS."""
|
"""Get FallbackDNS."""
|
||||||
return [
|
return [
|
||||||
(0, 2, bytes([1, 1, 1, 1])),
|
[0, 2, bytes([1, 1, 1, 1])],
|
||||||
(
|
[
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
bytes(
|
bytes(
|
||||||
@@ -133,15 +133,15 @@ class Resolved(DBusServiceMock):
|
|||||||
0x11,
|
0x11,
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def FallbackDNSEx(self) -> "a(iiayqs)":
|
def FallbackDNSEx(self) -> "a(iiayqs)":
|
||||||
"""Get FallbackDNSEx."""
|
"""Get FallbackDNSEx."""
|
||||||
return [
|
return [
|
||||||
(0, 2, bytes([1, 1, 1, 1]), 0, "cloudflare-dns.com"),
|
[0, 2, bytes([1, 1, 1, 1]), 0, "cloudflare-dns.com"],
|
||||||
(
|
[
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
bytes(
|
bytes(
|
||||||
@@ -166,33 +166,33 @@ class Resolved(DBusServiceMock):
|
|||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
"cloudflare-dns.com",
|
"cloudflare-dns.com",
|
||||||
),
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def CurrentDNSServer(self) -> "(iiay)":
|
def CurrentDNSServer(self) -> "(iiay)":
|
||||||
"""Get CurrentDNSServer."""
|
"""Get CurrentDNSServer."""
|
||||||
return (0, 2, bytes([127, 0, 0, 1]))
|
return [0, 2, bytes([127, 0, 0, 1])]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def CurrentDNSServerEx(self) -> "(iiayqs)":
|
def CurrentDNSServerEx(self) -> "(iiayqs)":
|
||||||
"""Get CurrentDNSServerEx."""
|
"""Get CurrentDNSServerEx."""
|
||||||
return (0, 2, bytes([127, 0, 0, 1]), 0, "")
|
return [0, 2, bytes([127, 0, 0, 1]), 0, ""]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def Domains(self) -> "a(isb)":
|
def Domains(self) -> "a(isb)":
|
||||||
"""Get Domains."""
|
"""Get Domains."""
|
||||||
return [(0, "local.hass.io", False)]
|
return [[0, "local.hass.io", False]]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def TransactionStatistics(self) -> "(tt)":
|
def TransactionStatistics(self) -> "(tt)":
|
||||||
"""Get TransactionStatistics."""
|
"""Get TransactionStatistics."""
|
||||||
return (0, 100000)
|
return [0, 100000]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def CacheStatistics(self) -> "(ttt)":
|
def CacheStatistics(self) -> "(ttt)":
|
||||||
"""Get CacheStatistics."""
|
"""Get CacheStatistics."""
|
||||||
return (10, 50000, 10000)
|
return [10, 50000, 10000]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def DNSSEC(self) -> "s":
|
def DNSSEC(self) -> "s":
|
||||||
@@ -202,7 +202,7 @@ class Resolved(DBusServiceMock):
|
|||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def DNSSECStatistics(self) -> "(tttt)":
|
def DNSSECStatistics(self) -> "(tttt)":
|
||||||
"""Get DNSSECStatistics."""
|
"""Get DNSSECStatistics."""
|
||||||
return (0, 0, 0, 0)
|
return [0, 0, 0, 0]
|
||||||
|
|
||||||
@dbus_property(access=PropertyAccess.READ)
|
@dbus_property(access=PropertyAccess.READ)
|
||||||
def DNSSECSupported(self) -> "b":
|
def DNSSECSupported(self) -> "b":
|
||||||
|
|||||||
@@ -119,10 +119,10 @@ async def test_load(
|
|||||||
"mnt-data-supervisor-mounts-backup_test.mount",
|
"mnt-data-supervisor-mounts-backup_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "noserverino,guest")),
|
["Options", Variant("s", "noserverino,guest")],
|
||||||
("Type", Variant("s", "cifs")),
|
["Type", Variant("s", "cifs")],
|
||||||
("Description", Variant("s", "Supervisor cifs mount: backup_test")),
|
["Description", Variant("s", "Supervisor cifs mount: backup_test")],
|
||||||
("What", Variant("s", "//backup.local/backups")),
|
["What", Variant("s", "//backup.local/backups")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -130,10 +130,10 @@ async def test_load(
|
|||||||
"mnt-data-supervisor-mounts-media_test.mount",
|
"mnt-data-supervisor-mounts-media_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "soft,timeo=200")),
|
["Options", Variant("s", "soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: media_test")),
|
["Description", Variant("s", "Supervisor nfs mount: media_test")],
|
||||||
("What", Variant("s", "media.local:/media")),
|
["What", Variant("s", "media.local:/media")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -141,12 +141,12 @@ async def test_load(
|
|||||||
"mnt-data-supervisor-media-media_test.mount",
|
"mnt-data-supervisor-media-media_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "bind")),
|
["Options", Variant("s", "bind")],
|
||||||
(
|
[
|
||||||
"Description",
|
"Description",
|
||||||
Variant("s", "Supervisor bind mount: bind_media_test"),
|
Variant("s", "Supervisor bind mount: bind_media_test"),
|
||||||
),
|
],
|
||||||
("What", Variant("s", "/mnt/data/supervisor/mounts/media_test")),
|
["What", Variant("s", "/mnt/data/supervisor/mounts/media_test")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -198,10 +198,10 @@ async def test_load_share_mount(
|
|||||||
"mnt-data-supervisor-mounts-share_test.mount",
|
"mnt-data-supervisor-mounts-share_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "soft,timeo=200")),
|
["Options", Variant("s", "soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: share_test")),
|
["Description", Variant("s", "Supervisor nfs mount: share_test")],
|
||||||
("What", Variant("s", "share.local:/share")),
|
["What", Variant("s", "share.local:/share")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -209,9 +209,9 @@ async def test_load_share_mount(
|
|||||||
"mnt-data-supervisor-share-share_test.mount",
|
"mnt-data-supervisor-share-share_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "bind")),
|
["Options", Variant("s", "bind")],
|
||||||
("Description", Variant("s", "Supervisor bind mount: bind_share_test")),
|
["Description", Variant("s", "Supervisor bind mount: bind_share_test")],
|
||||||
("What", Variant("s", "/mnt/data/supervisor/mounts/share_test")),
|
["What", Variant("s", "/mnt/data/supervisor/mounts/share_test")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -318,12 +318,12 @@ async def test_mount_failed_during_load(
|
|||||||
"mnt-data-supervisor-media-media_test.mount",
|
"mnt-data-supervisor-media-media_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "ro,bind")),
|
["Options", Variant("s", "ro,bind")],
|
||||||
(
|
[
|
||||||
"Description",
|
"Description",
|
||||||
Variant("s", "Supervisor bind mount: emergency_media_test"),
|
Variant("s", "Supervisor bind mount: emergency_media_test"),
|
||||||
),
|
],
|
||||||
("What", Variant("s", "/mnt/data/supervisor/emergency/media_test")),
|
["What", Variant("s", "/mnt/data/supervisor/emergency/media_test")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -634,10 +634,10 @@ async def test_reload_mounts_attempts_initial_mount(
|
|||||||
"mnt-data-supervisor-mounts-media_test.mount",
|
"mnt-data-supervisor-mounts-media_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "soft,timeo=200")),
|
["Options", Variant("s", "soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: media_test")),
|
["Description", Variant("s", "Supervisor nfs mount: media_test")],
|
||||||
("What", Variant("s", "media.local:/media")),
|
["What", Variant("s", "media.local:/media")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
@@ -645,9 +645,9 @@ async def test_reload_mounts_attempts_initial_mount(
|
|||||||
"mnt-data-supervisor-media-media_test.mount",
|
"mnt-data-supervisor-media-media_test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "bind")),
|
["Options", Variant("s", "bind")],
|
||||||
("Description", Variant("s", "Supervisor bind mount: bind_media_test")),
|
["Description", Variant("s", "Supervisor bind mount: bind_media_test")],
|
||||||
("What", Variant("s", "/mnt/data/supervisor/mounts/media_test")),
|
["What", Variant("s", "/mnt/data/supervisor/mounts/media_test")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ async def test_cifs_mount(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
(
|
[
|
||||||
"Options",
|
"Options",
|
||||||
Variant(
|
Variant(
|
||||||
"s",
|
"s",
|
||||||
@@ -117,10 +117,10 @@ async def test_cifs_mount(
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
("Type", Variant("s", "cifs")),
|
["Type", Variant("s", "cifs")],
|
||||||
("Description", Variant("s", "Supervisor cifs mount: test")),
|
["Description", Variant("s", "Supervisor cifs mount: test")],
|
||||||
("What", Variant("s", "//test.local/camera")),
|
["What", Variant("s", "//test.local/camera")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -177,10 +177,10 @@ async def test_cifs_mount_read_only(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "ro,noserverino,guest")),
|
["Options", Variant("s", "ro,noserverino,guest")],
|
||||||
("Type", Variant("s", "cifs")),
|
["Type", Variant("s", "cifs")],
|
||||||
("Description", Variant("s", "Supervisor cifs mount: test")),
|
["Description", Variant("s", "Supervisor cifs mount: test")],
|
||||||
("What", Variant("s", "//test.local/camera")),
|
["What", Variant("s", "//test.local/camera")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -237,10 +237,10 @@ async def test_nfs_mount(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "port=1234,soft,timeo=200")),
|
["Options", Variant("s", "port=1234,soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: test")),
|
["Description", Variant("s", "Supervisor nfs mount: test")],
|
||||||
("What", Variant("s", "test.local:/media/camera")),
|
["What", Variant("s", "test.local:/media/camera")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -283,10 +283,10 @@ async def test_nfs_mount_read_only(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "ro,port=1234,soft,timeo=200")),
|
["Options", Variant("s", "ro,port=1234,soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: test")),
|
["Description", Variant("s", "Supervisor nfs mount: test")],
|
||||||
("What", Variant("s", "test.local:/media/camera")),
|
["What", Variant("s", "test.local:/media/camera")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -331,10 +331,10 @@ async def test_load(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "noserverino,guest")),
|
["Options", Variant("s", "noserverino,guest")],
|
||||||
("Type", Variant("s", "cifs")),
|
["Type", Variant("s", "cifs")],
|
||||||
("Description", Variant("s", "Supervisor cifs mount: test")),
|
["Description", Variant("s", "Supervisor cifs mount: test")],
|
||||||
("What", Variant("s", "//test.local/share")),
|
["What", Variant("s", "//test.local/share")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
@@ -736,10 +736,10 @@ async def test_mount_fails_if_down(
|
|||||||
"mnt-data-supervisor-mounts-test.mount",
|
"mnt-data-supervisor-mounts-test.mount",
|
||||||
"fail",
|
"fail",
|
||||||
[
|
[
|
||||||
("Options", Variant("s", "port=1234,soft,timeo=200")),
|
["Options", Variant("s", "port=1234,soft,timeo=200")],
|
||||||
("Type", Variant("s", "nfs")),
|
["Type", Variant("s", "nfs")],
|
||||||
("Description", Variant("s", "Supervisor nfs mount: test")),
|
["Description", Variant("s", "Supervisor nfs mount: test")],
|
||||||
("What", Variant("s", "test.local:/media/camera")),
|
["What", Variant("s", "test.local:/media/camera")],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
from supervisor.const import CoreState
|
from supervisor.const import CoreState
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.resolution.evaluations.operating_system import EvaluateOperatingSystem
|
from supervisor.resolution.evaluations.operating_system import (
|
||||||
|
SUPPORTED_OS,
|
||||||
|
EvaluateOperatingSystem,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_evaluation(coresys: CoreSys):
|
async def test_evaluation(coresys: CoreSys):
|
||||||
@@ -22,7 +25,13 @@ async def test_evaluation(coresys: CoreSys):
|
|||||||
assert operating_system.reason in coresys.resolution.unsupported
|
assert operating_system.reason in coresys.resolution.unsupported
|
||||||
|
|
||||||
coresys.os._available = True
|
coresys.os._available = True
|
||||||
assert coresys.os.available
|
await operating_system()
|
||||||
|
assert operating_system.reason not in coresys.resolution.unsupported
|
||||||
|
coresys.os._available = False
|
||||||
|
|
||||||
|
coresys.host._info = MagicMock(
|
||||||
|
operating_system=SUPPORTED_OS[0], timezone=None, timezone_tzinfo=None
|
||||||
|
)
|
||||||
await operating_system()
|
await operating_system()
|
||||||
assert operating_system.reason not in coresys.resolution.unsupported
|
assert operating_system.reason not in coresys.resolution.unsupported
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
"""Test evaluation supported system architectures."""
|
|
||||||
|
|
||||||
from unittest.mock import PropertyMock, patch
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from supervisor.const import CoreState
|
|
||||||
from supervisor.coresys import CoreSys
|
|
||||||
from supervisor.resolution.evaluations.system_architecture import (
|
|
||||||
EvaluateSystemArchitecture,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("arch", ["i386", "armhf", "armv7"])
|
|
||||||
async def test_evaluation_unsupported_architectures(
|
|
||||||
coresys: CoreSys,
|
|
||||||
arch: str,
|
|
||||||
):
|
|
||||||
"""Test evaluation of unsupported system architectures."""
|
|
||||||
system_architecture = EvaluateSystemArchitecture(coresys)
|
|
||||||
await coresys.core.set_state(CoreState.INITIALIZE)
|
|
||||||
|
|
||||||
with patch.object(
|
|
||||||
type(coresys.supervisor), "arch", PropertyMock(return_value=arch)
|
|
||||||
):
|
|
||||||
await system_architecture()
|
|
||||||
assert system_architecture.reason in coresys.resolution.unsupported
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("arch", ["amd64", "aarch64"])
|
|
||||||
async def test_evaluation_supported_architectures(
|
|
||||||
coresys: CoreSys,
|
|
||||||
arch: str,
|
|
||||||
):
|
|
||||||
"""Test evaluation of supported system architectures."""
|
|
||||||
system_architecture = EvaluateSystemArchitecture(coresys)
|
|
||||||
await coresys.core.set_state(CoreState.INITIALIZE)
|
|
||||||
|
|
||||||
with patch.object(
|
|
||||||
type(coresys.supervisor), "arch", PropertyMock(return_value=arch)
|
|
||||||
):
|
|
||||||
await system_architecture()
|
|
||||||
assert system_architecture.reason not in coresys.resolution.unsupported
|
|
||||||
Reference in New Issue
Block a user