Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
95d6a84
Add Backblaze B2 integration
hugo-vrijswijk May 23, 2025
c4c6f82
Add tests for backup and init
hugo-vrijswijk May 23, 2025
f733e4f
Improve test coverage
hugo-vrijswijk May 23, 2025
7d70e5a
Update log-when-unavailable quality_scale
hugo-vrijswijk May 23, 2025
fa22761
Rename backblaze_b2 to backblaze
hugo-vrijswijk May 26, 2025
162c938
Wrap in single executor job
hugo-vrijswijk May 26, 2025
25a7357
Extract AgentBackup creation to method
hugo-vrijswijk May 26, 2025
4270be9
Remove info log
hugo-vrijswijk Jun 2, 2025
fe3e373
Automatically add prefix slash
hugo-vrijswijk Jun 2, 2025
cfdabe5
Remove cast
hugo-vrijswijk Jun 6, 2025
7e56b87
Move some code outside try-catch
hugo-vrijswijk Jun 13, 2025
45bb33f
Update translation string for prefix directory path
hugo-vrijswijk Jun 13, 2025
cbcf31d
Use unique entry_id
hugo-vrijswijk Jun 13, 2025
bcbf2d3
Update imports and assert step_id and errors
hugo-vrijswijk Jun 13, 2025
b385011
Fix test
hugo-vrijswijk Jun 13, 2025
1676eac
Working implementation of file-based metadata. Tests passing.
ElCruncharino Jul 25, 2025
27d50ad
Refactoring and improvements
ElCruncharino Jul 25, 2025
3af63fe
Increase test coverage to 97%
ElCruncharino Jul 25, 2025
09de455
Updated to 98% coverage in tests.
ElCruncharino Jul 25, 2025
06070dd
Updated to fix upload/download
ElCruncharino Jul 28, 2025
80fec49
Allow for multipart uploads
ElCruncharino Jul 28, 2025
5878ef1
Fixed tests
ElCruncharino Jul 28, 2025
5393caf
Updates for downloading backups, and some test changes.
ElCruncharino Jul 28, 2025
f95f7db
Updated some tests and improved upload sequence
ElCruncharino Jul 28, 2025
ba347fe
Improved tests and cleaned up comments
ElCruncharino Jul 28, 2025
cc7b345
Continued updates to tests. Minor tweaks to backup for multipart uplo…
ElCruncharino Jul 28, 2025
e66005e
Improved coverage
ElCruncharino Jul 28, 2025
6a5f8cc
98% coverage
ElCruncharino Jul 28, 2025
79ed74d
100% coverage
ElCruncharino Jul 28, 2025
d5d4ff5
Refactoring, and simpler tests
ElCruncharino Jul 29, 2025
3b105d8
Revert to large test suite with 100% coverage.
ElCruncharino Jul 29, 2025
afc2d8e
Added caching
ElCruncharino Jul 29, 2025
e9449db
Refactoring of some tests and config flow.
ElCruncharino Jul 29, 2025
dacf44b
enhance backblaze integration to gold quality scale
ElCruncharino Sep 6, 2025
1d9f24a
logging import for config_flow
ElCruncharino Sep 6, 2025
f39a122
consolidate backblaze tests, reduce by 58% while keeping 100% coverage
ElCruncharino Sep 6, 2025
332c2f8
improve backblaze test coverage from 84% to 91%
ElCruncharino Sep 6, 2025
0b81f61
add safety limits and validation to backblaze component
ElCruncharino Sep 6, 2025
b930078
improve backblaze test coverage to 94%
ElCruncharino Sep 6, 2025
61d5f0b
add targeted tests to improve coverage to 93%
ElCruncharino Sep 6, 2025
f4830a9
add targeted tests for 94% coverage
ElCruncharino Sep 6, 2025
80b0962
reach 94% coverage with line 583 cache scenario
ElCruncharino Sep 6, 2025
dbf6a27
refactor backblaze test suite
ElCruncharino Sep 6, 2025
d399768
fixed linting
ElCruncharino Sep 7, 2025
1678def
updated JSON metadata formatting
ElCruncharino Sep 10, 2025
172b01c
address emontnemery review feedback for backblaze integration
ElCruncharino Sep 16, 2025
e2dd728
fix: use correct B2 SDK upload_unbound_stream method
ElCruncharino Sep 16, 2025
b6255a7
address emontnemery followup review feedback for backblaze integration
ElCruncharino Sep 18, 2025
d46014f
Added a couple of helper functions, and reconfigured tests.
ElCruncharino Sep 21, 2025
a467a27
inject "Backblaze" via description_placeholders & rename component t…
ElCruncharino Sep 25, 2025
eaefc50
address emontnemery's review points in pull request
ElCruncharino Sep 25, 2025
23bef05
Update homeassistant/components/backblaze_b2/__init__.py
ElCruncharino Sep 25, 2025
35df9e5
Update 'Backblaze' references to 'Backblaze B2' to match new componen…
ElCruncharino Sep 25, 2025
d9237d4
Removed dels from incorrect linting config. Cleaned up some tests.
ElCruncharino Sep 26, 2025
51a50c2
Update homeassistant/components/backblaze_b2/backup.py
ElCruncharino Sep 29, 2025
74bd084
rewrite guard clauses for _process_metadata_file_for_id_sync
ElCruncharino Sep 29, 2025
b5b15be
AsyncIteratorReader: export or backup util. awaiting PR
ElCruncharino Sep 29, 2025
262f776
refactor some ugly functions, address pull request feedback
ElCruncharino Sep 29, 2025
de01635
refactor backblaze test suite for maintainability
ElCruncharino Oct 6, 2025
e8cb1e0
WIP: test simplification. Get tests more in line with other backup in…
ElCruncharino Oct 6, 2025
2bfcd10
Update to try block for streaming
ElCruncharino Oct 14, 2025
2ea7aff
Except and else order change for partial cleanup of main backup file
ElCruncharino Oct 14, 2025
1d34e85
Per PR #153194, AsyncIteratorReader was moved away from backup integr…
ElCruncharino Oct 14, 2025
ace1fd9
Addresses recent Pull Request changes requested
ElCruncharino Oct 14, 2025
7657c52
Add backwards compatibility for AsyncIteratorReader in backblaze backup
ElCruncharino Oct 14, 2025
08881f8
Handle AsyncIteratorReader signature change in backblaze backup
ElCruncharino Oct 14, 2025
77cd724
added semaphores and test to prevent urllib3 connection pool exhaustion
ElCruncharino Oct 25, 2025
0c227b8
Address review concerns for semaphore and testing
ElCruncharino Oct 27, 2025
136a118
eliminated monkey patching and unused parameter linting adjustments
ElCruncharino Oct 28, 2025
efd338a
Merge branch 'dev' into integration-backblaze-b2
ElCruncharino Oct 29, 2025
f7e5ee9
Merge branch 'dev' into integration-backblaze-b2
ElCruncharino Oct 29, 2025
a3f4dd1
address reviewer changes, mostly to logging behavior (removed semaphore)
ElCruncharino Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ homeassistant.components.automation.*
homeassistant.components.awair.*
homeassistant.components.axis.*
homeassistant.components.azure_storage.*
homeassistant.components.backblaze_b2.*
homeassistant.components.backup.*
homeassistant.components.baf.*
homeassistant.components.bang_olufsen.*
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 116 additions & 0 deletions homeassistant/components/backblaze_b2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""The Backblaze B2 integration."""

from __future__ import annotations

from datetime import timedelta
import logging
from typing import Any

from b2sdk.v2 import B2Api, Bucket, InMemoryAccountInfo, exception

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.event import async_track_time_interval

from .const import (
BACKBLAZE_REALM,
CONF_APPLICATION_KEY,
CONF_BUCKET,
CONF_KEY_ID,
DATA_BACKUP_AGENT_LISTENERS,
DOMAIN,
)
from .repairs import (
async_check_for_repair_issues,
create_bucket_access_restricted_issue,
create_bucket_not_found_issue,
)

_LOGGER = logging.getLogger(__name__)

type BackblazeConfigEntry = ConfigEntry[Bucket]


async def async_setup_entry(hass: HomeAssistant, entry: BackblazeConfigEntry) -> bool:
"""Set up Backblaze B2 from a config entry."""

info = InMemoryAccountInfo()
b2_api = B2Api(info)

def _authorize_and_get_bucket_sync() -> Bucket:
"""Synchronously authorize the Backblaze B2 account and retrieve the bucket.

This function runs in the event loop's executor as b2sdk operations are blocking.
"""
b2_api.authorize_account(
BACKBLAZE_REALM,
entry.data[CONF_KEY_ID],
entry.data[CONF_APPLICATION_KEY],
)
return b2_api.get_bucket_by_name(entry.data[CONF_BUCKET])

try:
bucket = await hass.async_add_executor_job(_authorize_and_get_bucket_sync)
except exception.Unauthorized as err:
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="invalid_credentials",
) from err
except exception.RestrictedBucket as err:
create_bucket_access_restricted_issue(hass, entry, err.bucket_name)
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="restricted_bucket",
translation_placeholders={
"restricted_bucket_name": err.bucket_name,
},
) from err
except exception.NonExistentBucket as err:
create_bucket_not_found_issue(hass, entry, entry.data[CONF_BUCKET])
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="invalid_bucket_name",
) from err
except exception.ConnectionReset as err:
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="cannot_connect",
) from err
except exception.MissingAccountData as err:
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="invalid_auth",
) from err

entry.runtime_data = bucket

def _async_notify_backup_listeners() -> None:
"""Notify any registered backup agent listeners."""
_LOGGER.debug("Notifying backup listeners for entry %s", entry.entry_id)
for listener in hass.data.get(DATA_BACKUP_AGENT_LISTENERS, []):
listener()

entry.async_on_unload(entry.async_on_state_change(_async_notify_backup_listeners))

async def _periodic_issue_check(_now: Any) -> None:
"""Periodically check for repair issues."""
await async_check_for_repair_issues(hass, entry)

entry.async_on_unload(
async_track_time_interval(hass, _periodic_issue_check, timedelta(minutes=30))
)

hass.async_create_task(async_check_for_repair_issues(hass, entry))

return True


async def async_unload_entry(hass: HomeAssistant, entry: BackblazeConfigEntry) -> bool:
"""Unload a Backblaze B2 config entry.

Any resources directly managed by this entry that need explicit shutdown
would be handled here. In this case, the `async_on_state_change` listener
handles the notification logic on unload.
"""
return True
Loading
Loading