Skip to content

Commit d285fd4

Browse files
authored
Fix handling with docker container (#7)
* Fix handling with docker container * Fix lint * update version * fix lint v2 * fix signal handling * fix log output
1 parent 7a0b9cc commit d285fd4

File tree

10 files changed

+82
-37
lines changed

10 files changed

+82
-37
lines changed

hassio/__main__.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Main file for HassIO."""
22
import asyncio
33
import logging
4-
import signal
54
import sys
65

76
import hassio.bootstrap as bootstrap
@@ -25,12 +24,7 @@
2524

2625
_LOGGER.info("Start Hassio task")
2726
loop.call_soon_threadsafe(loop.create_task, hassio.start())
28-
29-
try:
30-
loop.add_signal_handler(
31-
signal.SIGTERM, lambda: loop.create_task(hassio.stop()))
32-
except ValueError:
33-
_LOGGER.warning("Could not bind to SIGTERM")
27+
loop.call_soon_threadsafe(bootstrap.reg_signal, loop, hassio)
3428

3529
loop.run_forever()
3630
loop.close()

hassio/bootstrap.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import os
44
import stat
5+
import signal
56

67
from colorlog import ColoredFormatter
78

@@ -81,3 +82,24 @@ def check_environment():
8182
return False
8283

8384
return True
85+
86+
87+
def reg_signal(loop, hassio):
88+
"""Register SIGTERM, SIGKILL to stop system."""
89+
try:
90+
loop.add_signal_handler(
91+
signal.SIGTERM, lambda: loop.create_task(hassio.stop()))
92+
except (ValueError, RuntimeError):
93+
_LOGGER.warning("Could not bind to SIGTERM")
94+
95+
try:
96+
loop.add_signal_handler(
97+
signal.SIGHUP, lambda: loop.create_task(hassio.stop()))
98+
except (ValueError, RuntimeError):
99+
_LOGGER.warning("Could not bind to SIGHUP")
100+
101+
try:
102+
loop.add_signal_handler(
103+
signal.SIGINT, lambda: loop.create_task(hassio.stop()))
104+
except (ValueError, RuntimeError):
105+
_LOGGER.warning("Could not bind to SIGINT")

hassio/config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
UPSTREAM_BETA = 'upstream_beta'
2424

25+
API_ENDPOINT = 'api_endpoint'
26+
2527

2628
class Config(object):
2729
"""Hold all config data."""
@@ -78,6 +80,16 @@ async def fetch_update_infos(self):
7880

7981
return False
8082

83+
@property
84+
def api_endpoint(self):
85+
"""Return IP address of api endpoint."""
86+
return self._data[API_ENDPOINT]
87+
88+
@api_endpoint.setter
89+
def api_endpoint(self, value):
90+
"""Store IP address of api endpoint."""
91+
self._data[API_ENDPOINT] = value
92+
8193
@property
8294
def upstream_beta(self):
8395
"""Return True if we run in beta upstream."""

hassio/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Const file for HassIO."""
2-
HASSIO_VERSION = '0.8'
2+
HASSIO_VERSION = '0.9'
33

44
URL_HASSIO_VERSION = \
55
'https://raw.githubusercontent.com/pvizeli/hassio/master/version.json'

hassio/core.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from .scheduler import Scheduler
1616
from .dock.homeassistant import DockerHomeAssistant
1717
from .dock.supervisor import DockerSupervisor
18-
from .tools import get_arch_from_image
18+
from .tools import get_arch_from_image, get_local_ip
1919

2020
_LOGGER = logging.getLogger(__name__)
2121

@@ -52,6 +52,9 @@ async def setup(self):
5252
await self.supervisor.attach()
5353
await self.supervisor.cleanup()
5454

55+
# set api endpoint
56+
self.config.api_endpoint = await get_local_ip(self.loop)
57+
5558
# hostcontroll
5659
host_info = await self.host_controll.info()
5760
if host_info:
@@ -72,7 +75,7 @@ async def setup(self):
7275
# schedule update info tasks
7376
self.scheduler.register_task(
7477
self.config.fetch_update_infos, RUN_UPDATE_INFO_TASKS,
75-
first_run=True)
78+
now=True)
7679

7780
# first start of supervisor?
7881
if not await self.homeassistant.exists():
@@ -85,7 +88,7 @@ async def setup(self):
8588

8689
# schedule addon update task
8790
self.scheduler.register_task(
88-
self.addons.relaod, RUN_RELOAD_ADDONS_TASKS, first_run=True)
91+
self.addons.relaod, RUN_RELOAD_ADDONS_TASKS, now=True)
8992

9093
# schedule self update task
9194
self.scheduler.register_task(
@@ -95,6 +98,7 @@ async def start(self):
9598
"""Start HassIO orchestration."""
9699
# start api
97100
await self.api.start()
101+
_LOGGER.info("Start hassio api on %s", self.config.api_endpoint)
98102

99103
# HomeAssistant is already running / supervisor have only reboot
100104
if await self.homeassistant.is_running():
@@ -112,6 +116,10 @@ async def start(self):
112116

113117
async def stop(self, exit_code=0):
114118
"""Stop a running orchestration."""
119+
# don't process scheduler anymore
120+
self.scheduler.stop()
121+
122+
# process stop task pararell
115123
tasks = [self.websession.close(), self.api.stop()]
116124
await asyncio.wait(tasks, loop=self.loop)
117125

hassio/dock/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,6 @@ async def run(self):
138138
return False
139139

140140
async with self._lock:
141-
_LOGGER.info("Run docker image %s with version %s",
142-
self.image, self.version)
143141
return await self.loop.run_in_executor(None, self._run)
144142

145143
def _run(self):

hassio/dock/addon.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ def _run(self):
6565
detach=True,
6666
network_mode='bridge',
6767
ports=self.addons_data.get_ports(self.addon),
68-
restart_policy={
69-
"Name": "on-failure",
70-
"MaximumRetryCount": 10,
71-
},
7268
volumes=volumes,
7369
)
7470

7571
self.version = get_version_from_env(
7672
self.container.attrs['Config']['Env'])
73+
74+
_LOGGER.info("Start docker addon %s with version %s",
75+
self.image, self.version)
76+
7777
except docker.errors.DockerException as err:
7878
_LOGGER.error("Can't run %s -> %s", self.image, err)
7979
return False

hassio/dock/homeassistant.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import docker
55

66
from . import DockerBase
7-
from ..tools import get_version_from_env, get_local_ip
7+
from ..tools import get_version_from_env
88

99
_LOGGER = logging.getLogger(__name__)
1010

@@ -31,8 +31,6 @@ def _run(self):
3131
if self._is_running():
3232
return
3333

34-
api_endpoint = get_local_ip(self.loop)
35-
3634
# cleanup old container
3735
self._stop()
3836

@@ -43,12 +41,8 @@ def _run(self):
4341
detach=True,
4442
privileged=True,
4543
network_mode='host',
46-
restart_policy={
47-
"Name": "always",
48-
"MaximumRetryCount": 10,
49-
},
5044
environment={
51-
'HASSIO': api_endpoint,
45+
'HASSIO': self.config.api_endpoint,
5246
},
5347
volumes={
5448
self.config.path_config_docker:
@@ -59,6 +53,10 @@ def _run(self):
5953

6054
self.version = get_version_from_env(
6155
self.container.attrs['Config']['Env'])
56+
57+
_LOGGER.info("Start docker addon %s with version %s",
58+
self.image, self.version)
59+
6260
except docker.errors.DockerException as err:
6361
_LOGGER.error("Can't run %s -> %s", self.image, err)
6462
return False

hassio/scheduler.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ def __init__(self, loop):
1616
"""Initialize task schedule."""
1717
self.loop = loop
1818
self._data = {}
19+
self._stop = False
20+
21+
def stop(self):
22+
"""Stop to execute tasks in scheduler."""
23+
self._stop = True
1924

2025
def register_task(self, coro_callback, seconds, repeat=True,
21-
first_run=False):
26+
now=False):
2227
"""Schedule a coroutine.
2328
2429
The coroutien need to be a callback without arguments.
@@ -34,7 +39,7 @@ def register_task(self, coro_callback, seconds, repeat=True,
3439
self._data[idx] = opts
3540

3641
# schedule task
37-
if first_run:
42+
if now:
3843
self._run_task(idx)
3944
else:
4045
task = self.loop.call_later(seconds, self._run_task, idx)
@@ -46,6 +51,10 @@ def _run_task(self, idx):
4651
"""Run a scheduled task."""
4752
data = self._data.pop(idx)
4853

54+
# stop execute tasks
55+
if self._stop:
56+
return
57+
4958
self.loop.create_task(data[CALL]())
5059

5160
if data[REPEAT]:

hassio/tools.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,23 @@ def get_version_from_env(env_list):
5555
def get_local_ip(loop):
5656
"""Retrieve local IP address.
5757
58-
Need run inside executor.
58+
Return a future.
5959
"""
60-
try:
61-
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
60+
def local_ip():
61+
"""Return local ip."""
62+
try:
63+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
64+
65+
# Use Google Public DNS server to determine own IP
66+
sock.connect(('8.8.8.8', 80))
6267

63-
# Use Google Public DNS server to determine own IP
64-
sock.connect(('8.8.8.8', 80))
68+
return sock.getsockname()[0]
69+
except socket.error:
70+
return socket.gethostbyname(socket.gethostname())
71+
finally:
72+
sock.close()
6573

66-
return sock.getsockname()[0]
67-
except socket.error:
68-
return socket.gethostbyname(socket.gethostname())
69-
finally:
70-
sock.close()
74+
return loop.run_in_executor(None, local_ip)
7175

7276

7377
def write_json_file(jsonfile, data):

0 commit comments

Comments
 (0)