Home Assistant Unofficial Reference 2024.12.1
repairs.py
Go to the documentation of this file.
1 """Repairs implementation for the cloud integration."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from typing import Any
7 
8 import voluptuous as vol
9 
11  ConfirmRepairFlow,
12  RepairsFlow,
13  repairs_flow_manager,
14 )
15 from homeassistant.core import HomeAssistant, callback
16 from homeassistant.data_entry_flow import FlowResult
17 from homeassistant.helpers import issue_registry as ir
18 
19 from .const import DATA_CLOUD, DOMAIN
20 from .subscription import async_migrate_paypal_agreement, async_subscription_info
21 
22 BACKOFF_TIME = 5
23 MAX_RETRIES = 60 # This allows for 10 minutes of retries
24 
25 
26 @callback
28  hass: HomeAssistant,
29  subscription_info: dict[str, Any],
30 ) -> None:
31  """Manage the legacy subscription issue.
32 
33  If the provider is "legacy" create an issue,
34  in all other cases remove the issue.
35  """
36  if subscription_info.get("provider") == "legacy":
37  ir.async_create_issue(
38  hass=hass,
39  domain=DOMAIN,
40  issue_id="legacy_subscription",
41  is_fixable=True,
42  severity=ir.IssueSeverity.WARNING,
43  translation_key="legacy_subscription",
44  )
45  return
46  ir.async_delete_issue(hass=hass, domain=DOMAIN, issue_id="legacy_subscription")
47 
48 
49 class LegacySubscriptionRepairFlow(RepairsFlow):
50  """Handler for an issue fixing flow."""
51 
52  wait_task: asyncio.Task | None = None
53  _data: dict[str, Any] | None = None
54 
55  async def async_step_init(self, _: None = None) -> FlowResult:
56  """Handle the first step of a fix flow."""
57  return await self.async_step_confirm_change_plan()
58 
59  async def async_step_confirm_change_plan(
60  self,
61  user_input: dict[str, str] | None = None,
62  ) -> FlowResult:
63  """Handle the confirm step of a fix flow."""
64  if user_input is not None:
65  return await self.async_step_change_plan()
66 
67  return self.async_show_form(
68  step_id="confirm_change_plan", data_schema=vol.Schema({})
69  )
70 
71  async def async_step_change_plan(self, _: None = None) -> FlowResult:
72  """Wait for the user to authorize the app installation."""
73 
74  cloud = self.hass.data[DATA_CLOUD]
75 
76  async def _async_wait_for_plan_change() -> None:
77  flow_manager = repairs_flow_manager(self.hass)
78  # We cannot get here without a flow manager
79  assert flow_manager is not None
80 
81  retries = 0
82  while retries < MAX_RETRIES:
83  self._data_data = await async_subscription_info(cloud)
84  if self._data_data is not None and self._data_data["provider"] != "legacy":
85  break
86 
87  retries += 1
88  await asyncio.sleep(BACKOFF_TIME)
89 
90  self.hass.async_create_task(
91  flow_manager.async_configure(flow_id=self.flow_id)
92  )
93 
94  if not self.wait_taskwait_task:
95  self.wait_taskwait_task = self.hass.async_create_task(
96  _async_wait_for_plan_change(), eager_start=False
97  )
98  migration = await async_migrate_paypal_agreement(cloud)
99  return self.async_external_step(
100  step_id="change_plan",
101  url=migration["url"] if migration else "https://account.nabucasa.com/",
102  )
103 
104  await self.wait_taskwait_task
105 
106  if self._data_data is None or self._data_data["provider"] == "legacy":
107  # If we get here we waited too long.
108  return self.async_external_step_done(next_step_id="timeout")
109 
110  return self.async_external_step_done(next_step_id="complete")
111 
112  async def async_step_complete(self, _: None = None) -> FlowResult:
113  """Handle the final step of a fix flow."""
114  return self.async_create_entry(data={})
115 
116  async def async_step_timeout(self, _: None = None) -> FlowResult:
117  """Handle the final step of a fix flow."""
118  return self.async_abort(reason="operation_took_too_long")
119 
120 
122  hass: HomeAssistant,
123  issue_id: str,
124  data: dict[str, str | int | float | None] | None,
125 ) -> RepairsFlow:
126  """Create flow."""
127  if issue_id == "legacy_subscription":
129  return ConfirmRepairFlow()
RepairsFlow async_create_fix_flow(HomeAssistant hass, str issue_id, dict[str, str|int|float|None]|None data)
Definition: repairs.py:125
None async_manage_legacy_subscription_issue(HomeAssistant hass, dict[str, Any] subscription_info)
Definition: repairs.py:30
dict[str, Any]|None async_migrate_paypal_agreement(Cloud[CloudClient] cloud)
Definition: subscription.py:39
dict[str, Any]|None async_subscription_info(Cloud[CloudClient] cloud)
Definition: subscription.py:18
RepairsFlowManager|None repairs_flow_manager(HomeAssistant hass)
Definition: __init__.py:24