diff --git a/API.md b/API.md index 94686d014..eedc77987 100644 --- a/API.md +++ b/API.md @@ -171,6 +171,8 @@ Optional: Output the raw docker log +- POST `/homeassistant/restart` + ### REST API addons - GET `/addons/{addon}/info` @@ -223,6 +225,8 @@ Optional: Output the raw docker log +- POST `/addons/{addon}/restart` + ## Host Control Communicate over unix socket with a host daemon. diff --git a/hassio/addons/__init__.py b/hassio/addons/__init__.py index dafef9cce..4ce17a22c 100644 --- a/hassio/addons/__init__.py +++ b/hassio/addons/__init__.py @@ -197,6 +197,14 @@ class AddonManager(AddonsData): return True return False + async def restart(self, addon): + """Restart addon.""" + if addon not in self.dockers: + _LOGGER.error("No docker found for addon %s", addon) + return False + + return await self.dockers[addon].restart() + async def logs(self, addon): """Return addons log output.""" if addon not in self.dockers: diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index 2ee224ab9..847021a56 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -64,6 +64,7 @@ class RestAPI(object): self.webapp.router.add_get('/homeassistant/info', api_hass.info) self.webapp.router.add_post('/homeassistant/update', api_hass.update) + self.webapp.router.add_post('/homeassistant/restart', api_hass.restart) self.webapp.router.add_get('/homeassistant/logs', api_hass.logs) def register_addons(self, addons): diff --git a/hassio/api/addons.py b/hassio/api/addons.py index b27afeb25..aeca30d12 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -143,6 +143,12 @@ class APIAddons(object): return await asyncio.shield( self.addons.update(addon, version), loop=self.loop) + @api_process + async def restart(self, request): + """Restart addon.""" + addon = self._extract_addon(request) + return await asyncio.shield(self.addons.restart(addon), loop=self.loop) + @api_process_raw def logs(self, request): """Return logs from addon.""" diff --git a/hassio/api/homeassistant.py b/hassio/api/homeassistant.py index a4d9786aa..35c8f67d5 100644 --- a/hassio/api/homeassistant.py +++ b/hassio/api/homeassistant.py @@ -35,7 +35,7 @@ class APIHomeAssistant(object): @api_process async def update(self, request): - """Update host OS.""" + """Update homeassistant.""" body = await api_validate(SCHEMA_VERSION, request) version = body.get(ATTR_VERSION, self.config.last_homeassistant) @@ -48,6 +48,15 @@ class APIHomeAssistant(object): return await asyncio.shield( self.homeassistant.update(version), loop=self.loop) + @api_process + async def restart(self, request): + """Restart homeassistant.""" + if self.homeassistant.in_progress: + raise RuntimeError("Other task is in progress") + + return await asyncio.shield( + self.homeassistant.restart(), loop=self.loop) + @api_process_raw def logs(self, request): """Return homeassistant docker logs. diff --git a/hassio/dock/__init__.py b/hassio/dock/__init__.py index 386627834..91fe973b9 100644 --- a/hassio/dock/__init__.py +++ b/hassio/dock/__init__.py @@ -264,3 +264,28 @@ class DockerBase(object): return self.container.logs(tail=100, stdout=True, stderr=True) except docker.errors.DockerException as err: _LOGGER.warning("Can't grap logs from %s -> %s", self.image, err) + + async def restart(self): + """Restart docker container.""" + if self._lock.locked(): + _LOGGER.error("Can't excute restart while a task is in progress") + return False + + async with self._lock: + return await self.loop.run_in_executor(None, self._restart) + + def _restart(self): + """Restart docker container. + + Need run inside executor. + """ + if not self.container: + return False + + try: + self.container.restart(timeout=30) + except docker.errors.DockerException as err: + _LOGGER.warning("Can't restart %s -> %s", self.image, err) + return False + + return True diff --git a/hassio/dock/supervisor.py b/hassio/dock/supervisor.py index 7d9179b3c..da9fbaa20 100644 --- a/hassio/dock/supervisor.py +++ b/hassio/dock/supervisor.py @@ -81,3 +81,7 @@ class DockerSupervisor(DockerBase): async def remove(self): """Remove docker image.""" raise RuntimeError("Not support on supervisor docker container!") + + async def restart(self): + """Restart docker container.""" + raise RuntimeError("Not support on supervisor docker container!")