Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dcb2087

Browse files
ElCruncharinohugo-vrijswijkemontnemery
authored
Add backblaze b2 backup integration (home-assistant#149627)
Co-authored-by: Hugo van Rijswijk <git@hugovr.nl> Co-authored-by: ElCruncharino <ElCruncharino@users.noreply.github.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>
1 parent 7de94f3 commit dcb2087

24 files changed

+3341
-0
lines changed

‎.strict-typing‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ homeassistant.components.automation.*
107107
homeassistant.components.awair.*
108108
homeassistant.components.axis.*
109109
homeassistant.components.azure_storage.*
110+
homeassistant.components.backblaze_b2.*
110111
homeassistant.components.backup.*
111112
homeassistant.components.baf.*
112113
homeassistant.components.bang_olufsen.*

‎CODEOWNERS‎

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""The Backblaze B2 integration."""
2+
3+
from __future__ import annotations
4+
5+
from datetime import timedelta
6+
import logging
7+
from typing import Any
8+
9+
from b2sdk.v2 import B2Api, Bucket, InMemoryAccountInfo, exception
10+
11+
from homeassistant.config_entries import ConfigEntry
12+
from homeassistant.core import HomeAssistant
13+
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
14+
from homeassistant.helpers.event import async_track_time_interval
15+
16+
from .const import (
17+
BACKBLAZE_REALM,
18+
CONF_APPLICATION_KEY,
19+
CONF_BUCKET,
20+
CONF_KEY_ID,
21+
DATA_BACKUP_AGENT_LISTENERS,
22+
DOMAIN,
23+
)
24+
from .repairs import (
25+
async_check_for_repair_issues,
26+
create_bucket_access_restricted_issue,
27+
create_bucket_not_found_issue,
28+
)
29+
30+
_LOGGER = logging.getLogger(__name__)
31+
32+
type BackblazeConfigEntry = ConfigEntry[Bucket]
33+
34+
35+
async def async_setup_entry(hass: HomeAssistant, entry: BackblazeConfigEntry) -> bool:
36+
"""Set up Backblaze B2 from a config entry."""
37+
38+
info = InMemoryAccountInfo()
39+
b2_api = B2Api(info)
40+
41+
def _authorize_and_get_bucket_sync() -> Bucket:
42+
"""Synchronously authorize the Backblaze B2 account and retrieve the bucket.
43+
44+
This function runs in the event loop's executor as b2sdk operations are blocking.
45+
"""
46+
b2_api.authorize_account(
47+
BACKBLAZE_REALM,
48+
entry.data[CONF_KEY_ID],
49+
entry.data[CONF_APPLICATION_KEY],
50+
)
51+
return b2_api.get_bucket_by_name(entry.data[CONF_BUCKET])
52+
53+
try:
54+
bucket = await hass.async_add_executor_job(_authorize_and_get_bucket_sync)
55+
except exception.Unauthorized as err:
56+
raise ConfigEntryAuthFailed(
57+
translation_domain=DOMAIN,
58+
translation_key="invalid_credentials",
59+
) from err
60+
except exception.RestrictedBucket as err:
61+
create_bucket_access_restricted_issue(hass, entry, err.bucket_name)
62+
raise ConfigEntryNotReady(
63+
translation_domain=DOMAIN,
64+
translation_key="restricted_bucket",
65+
translation_placeholders={
66+
"restricted_bucket_name": err.bucket_name,
67+
},
68+
) from err
69+
except exception.NonExistentBucket as err:
70+
create_bucket_not_found_issue(hass, entry, entry.data[CONF_BUCKET])
71+
raise ConfigEntryNotReady(
72+
translation_domain=DOMAIN,
73+
translation_key="invalid_bucket_name",
74+
) from err
75+
except exception.ConnectionReset as err:
76+
raise ConfigEntryNotReady(
77+
translation_domain=DOMAIN,
78+
translation_key="cannot_connect",
79+
) from err
80+
except exception.MissingAccountData as err:
81+
raise ConfigEntryAuthFailed(
82+
translation_domain=DOMAIN,
83+
translation_key="invalid_auth",
84+
) from err
85+
86+
entry.runtime_data = bucket
87+
88+
def _async_notify_backup_listeners() -> None:
89+
"""Notify any registered backup agent listeners."""
90+
_LOGGER.debug("Notifying backup listeners for entry %s", entry.entry_id)
91+
for listener in hass.data.get(DATA_BACKUP_AGENT_LISTENERS, []):
92+
listener()
93+
94+
entry.async_on_unload(entry.async_on_state_change(_async_notify_backup_listeners))
95+
96+
async def _periodic_issue_check(_now: Any) -> None:
97+
"""Periodically check for repair issues."""
98+
await async_check_for_repair_issues(hass, entry)
99+
100+
entry.async_on_unload(
101+
async_track_time_interval(hass, _periodic_issue_check, timedelta(minutes=30))
102+
)
103+
104+
hass.async_create_task(async_check_for_repair_issues(hass, entry))
105+
106+
return True
107+
108+
109+
async def async_unload_entry(hass: HomeAssistant, entry: BackblazeConfigEntry) -> bool:
110+
"""Unload a Backblaze B2 config entry.
111+
112+
Any resources directly managed by this entry that need explicit shutdown
113+
would be handled here. In this case, the `async_on_state_change` listener
114+
handles the notification logic on unload.
115+
"""
116+
return True

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /