diff --git a/hassio/const.py b/hassio/const.py index 002805399..443627d30 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -2,7 +2,7 @@ from pathlib import Path from ipaddress import ip_network -HASSIO_VERSION = '127' +HASSIO_VERSION = '128' URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons" URL_HASSIO_VERSION = \ diff --git a/hassio/homeassistant.py b/hassio/homeassistant.py index 660603632..bc94be29d 100644 --- a/hassio/homeassistant.py +++ b/hassio/homeassistant.py @@ -1,6 +1,7 @@ """HomeAssistant control object.""" import asyncio from contextlib import asynccontextmanager, suppress +from datetime import datetime, timedelta import logging import os import re @@ -46,6 +47,7 @@ class HomeAssistant(JsonConfig, CoreSysAttributes): self._error_state = False # We don't persist access tokens. Instead we fetch new ones when needed self.access_token = None + self._access_token_expires = None async def load(self): """Prepare HomeAssistant object.""" @@ -352,7 +354,8 @@ class HomeAssistant(JsonConfig, CoreSysAttributes): async def ensure_access_token(self): """Ensures there is an access token.""" - if self.access_token is not None: + if (self.access_token is not None and + self._access_token_expires > datetime.utcnow()): return with suppress(asyncio.TimeoutError, aiohttp.ClientError): @@ -364,14 +367,15 @@ class HomeAssistant(JsonConfig, CoreSysAttributes): "refresh_token": self.refresh_token } ) as resp: - if resp.status == 200: - _LOGGER.info("Updated HomeAssistant API token") - tokens = await resp.json() - self.access_token = tokens['access_token'] - return + if resp.status != 200: + _LOGGER.error("Can't update HomeAssistant access token!") + raise HomeAssistantAuthError() - _LOGGER.error("Can't update HomeAssistant access token!") - raise HomeAssistantAuthError() + _LOGGER.info("Updated HomeAssistant API token") + tokens = await resp.json() + self.access_token = tokens['access_token'] + self._access_token_expires = \ + datetime.utcnow() + timedelta(seconds=tokens['expires_in']) @asynccontextmanager async def make_request(self, method, path, json=None, content_type=None, diff --git a/hassio/snapshots/__init__.py b/hassio/snapshots/__init__.py index 749e3bb7f..f7f6c322f 100644 --- a/hassio/snapshots/__init__.py +++ b/hassio/snapshots/__init__.py @@ -293,6 +293,7 @@ class SnapshotManager(CoreSysAttributes): # Stop Home-Assistant if they will be restored later if homeassistant and FOLDER_HOMEASSISTANT in folders: await self.sys_homeassistant.stop() + snapshot.restore_homeassistant() # Process folders if folders: @@ -304,7 +305,6 @@ class SnapshotManager(CoreSysAttributes): if homeassistant: _LOGGER.info("Restore %s run Home-Assistant", snapshot.slug) - snapshot.restore_homeassistant() task_hass = self.sys_create_task( self.sys_homeassistant.update( snapshot.homeassistant_version)) @@ -322,12 +322,20 @@ class SnapshotManager(CoreSysAttributes): _LOGGER.info("Restore %s old add-ons", snapshot.slug) await snapshot.restore_addons(addon_list) - # make sure homeassistant run agen + # Make sure homeassistant run agen if task_hass: _LOGGER.info("Restore %s wait for Home-Assistant", snapshot.slug) await task_hass - await self.sys_homeassistant.start() + + # Do we need start HomeAssistant? + if not await self.sys_homeassistant.is_running(): + await self.sys_homeassistant.start() + + # Check If we can access to API / otherwise restart + if not await self.sys_homeassistant.check_api_state(): + _LOGGER.warning("Need restart HomeAssistant for API") + await self.sys_homeassistant.restart() except Exception: # pylint: disable=broad-except _LOGGER.exception("Restore %s error", snapshot.slug) diff --git a/hassio/snapshots/snapshot.py b/hassio/snapshots/snapshot.py index e737cb72a..11a6b5e68 100644 --- a/hassio/snapshots/snapshot.py +++ b/hassio/snapshots/snapshot.py @@ -20,7 +20,7 @@ from ..const import ( ATTR_HOMEASSISTANT, ATTR_FOLDERS, ATTR_VERSION, ATTR_TYPE, ATTR_IMAGE, ATTR_PORT, ATTR_SSL, ATTR_PASSWORD, ATTR_WATCHDOG, ATTR_BOOT, ATTR_CRYPTO, ATTR_LAST_VERSION, ATTR_PROTECTED, ATTR_WAIT_BOOT, ATTR_SIZE, - CRYPTO_AES128) + ATTR_REFRESH_TOKEN, CRYPTO_AES128) from ..coresys import CoreSysAttributes from ..utils.json import write_json_file from ..utils.tar import SecureTarFile @@ -387,6 +387,8 @@ class Snapshot(CoreSysAttributes): # API/Proxy self.homeassistant[ATTR_PORT] = self.sys_homeassistant.api_port self.homeassistant[ATTR_SSL] = self.sys_homeassistant.api_ssl + self.homeassistant[ATTR_REFRESH_TOKEN] = \ + self._encrypt_data(self.sys_homeassistant.refresh_token) self.homeassistant[ATTR_PASSWORD] = \ self._encrypt_data(self.sys_homeassistant.api_password) @@ -405,6 +407,8 @@ class Snapshot(CoreSysAttributes): # API/Proxy self.sys_homeassistant.api_port = self.homeassistant[ATTR_PORT] self.sys_homeassistant.api_ssl = self.homeassistant[ATTR_SSL] + self.sys_homeassistant.refresh_token = \ + self._decrypt_data(self.homeassistant[ATTR_REFRESH_TOKEN]) self.sys_homeassistant.api_password = \ self._decrypt_data(self.homeassistant[ATTR_PASSWORD]) diff --git a/hassio/snapshots/validate.py b/hassio/snapshots/validate.py index fa1681cba..8f8e39c34 100644 --- a/hassio/snapshots/validate.py +++ b/hassio/snapshots/validate.py @@ -7,6 +7,7 @@ from ..const import ( ATTR_VERSION, ATTR_HOMEASSISTANT, ATTR_FOLDERS, ATTR_TYPE, ATTR_IMAGE, ATTR_PASSWORD, ATTR_PORT, ATTR_SSL, ATTR_WATCHDOG, ATTR_BOOT, ATTR_SIZE, ATTR_LAST_VERSION, ATTR_WAIT_BOOT, ATTR_PROTECTED, ATTR_CRYPTO, + ATTR_REFRESH_TOKEN, FOLDER_SHARE, FOLDER_HOMEASSISTANT, FOLDER_ADDONS, FOLDER_SSL, SNAPSHOT_FULL, SNAPSHOT_PARTIAL, CRYPTO_AES128) from ..validate import NETWORK_PORT, REPOSITORIES, DOCKER_IMAGE @@ -40,6 +41,7 @@ SCHEMA_SNAPSHOT = vol.Schema({ vol.Optional(ATTR_SSL, default=False): vol.Boolean(), vol.Optional(ATTR_PORT, default=8123): NETWORK_PORT, vol.Optional(ATTR_PASSWORD): vol.Maybe(vol.Coerce(str)), + vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(vol.Coerce(str)), vol.Optional(ATTR_WATCHDOG, default=True): vol.Boolean(), vol.Optional(ATTR_WAIT_BOOT, default=600): vol.All(vol.Coerce(int), vol.Range(min=60)), diff --git a/requirements.txt b/requirements.txt index 32ebcdc4f..eae7f825f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,13 @@ attr==0.3.1 async_timeout==3.0.0 -aiohttp==3.3.2 +aiohttp==3.4.0 docker==3.5.0 colorlog==3.1.2 voluptuous==0.11.5 gitpython==2.1.10 pytz==2018.4 pyudev==0.21.0 -pycryptodome==3.6.4 +pycryptodome==3.6.6 cpe==1.2.1 uvloop==0.11.2 cchardet==2.1.1