diff --git a/API.md b/API.md index ddf383234a9..924e375a69e 100644 --- a/API.md +++ b/API.md @@ -34,6 +34,7 @@ The addons from `addons` are only installed one. "last_version": "LAST_VERSION", "arch": "armhf|aarch64|i386|amd64", "beta_channel": "true|false", + "timezone": "TIMEZONE", "addons": [ { "name": "xy bla", @@ -98,6 +99,7 @@ Optional: ```json { "beta_channel": "true|false", + "timezone": "TIMEZONE", "addons_repositories": [ "REPO_URL" ] diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index e4e0ae32bad..0b51d9be4e8 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -11,7 +11,8 @@ HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_REPOSITORIES, ATTR_REPOSITORY, ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED, ATTR_DETACHED, ATTR_SOURCE, ATTR_MAINTAINER, ATTR_URL, ATTR_ARCH, - ATTR_BUILD) + ATTR_BUILD, ATTR_TIMEZONE) +from ..tools import validate_timezone _LOGGER = logging.getLogger(__name__) @@ -19,6 +20,7 @@ # pylint: disable=no-value-for-parameter vol.Optional(ATTR_BETA_CHANNEL): vol.Boolean(), vol.Optional(ATTR_ADDONS_REPOSITORIES): [vol.Url()], + vol.Optional(ATTR_TIMEZONE): validate_timezone, }) SCHEMA_VERSION = vol.Schema({ @@ -92,6 +94,7 @@ async def info(self, request): ATTR_LAST_VERSION: self.config.last_hassio, ATTR_BETA_CHANNEL: self.config.upstream_beta, ATTR_ARCH: self.addons.arch, + ATTR_TIMEZONE: self.config.timezone, ATTR_ADDONS: self._addons_list(only_installed=True), ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories, } @@ -112,6 +115,9 @@ async def options(self, request): if ATTR_BETA_CHANNEL in body: self.config.upstream_beta = body[ATTR_BETA_CHANNEL] + if ATTR_TIMEZONE in body: + self.config.timezone = body[ATTR_TIMEZONE] + if ATTR_ADDONS_REPOSITORIES in body: new = set(body[ATTR_ADDONS_REPOSITORIES]) old = set(self.config.addons_repositories) diff --git a/hassio/config.py b/hassio/config.py index fd295cbacd5..7c0ff16f2dc 100644 --- a/hassio/config.py +++ b/hassio/config.py @@ -10,7 +10,7 @@ from .const import FILE_HASSIO_CONFIG, HASSIO_SHARE from .tools import ( - fetch_last_versions, write_json_file, read_json_file) + fetch_last_versions, write_json_file, read_json_file, validate_timezone) _LOGGER = logging.getLogger(__name__) @@ -35,8 +35,8 @@ SHARE_DATA = PurePath("share") UPSTREAM_BETA = 'upstream_beta' - API_ENDPOINT = 'api_endpoint' +TIMEZONE = 'timezone' SECURITY_INITIALIZE = 'security_initialize' SECURITY_TOTP = 'security_totp' @@ -48,6 +48,7 @@ SCHEMA_CONFIG = vol.Schema({ vol.Optional(UPSTREAM_BETA, default=False): vol.Boolean(), vol.Optional(API_ENDPOINT): vol.Coerce(str), + vol.Optional(TIMEZONE, default='UTC'): validate_timezone, vol.Optional(HOMEASSISTANT_LAST): vol.Coerce(str), vol.Optional(HASSIO_LAST): vol.Coerce(str), vol.Optional(HASSIO_CLEANUP): vol.Coerce(str), @@ -136,6 +137,17 @@ def upstream_beta(self, value): """Set beta upstream mode.""" self._data[UPSTREAM_BETA] = bool(value) + @property + def timezone(self): + """Return system timezone.""" + return self._data[TIMEZONE] + + @timezone.setter + def timezone(self, value): + """Set system timezone.""" + self._data[TIMEZONE] = value + self.save() + @property def hassio_cleanup(self): """Return Version they need to cleanup.""" diff --git a/hassio/const.py b/hassio/const.py index 1d55967a45a..86cc8b5c045 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -43,6 +43,7 @@ ATTR_ARCH = 'arch' ATTR_HOSTNAME = 'hostname' +ATTR_TIMEZONE = 'timezone' ATTR_OS = 'os' ATTR_TYPE = 'type' ATTR_SOURCE = 'source' diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index d4613db3e0a..6c8a0ba8b68 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -28,6 +28,16 @@ def docker_name(self): """Return name of docker container.""" return "addon_{}".format(self.addon) + @property + def environment(self): + """Return environment for docker add-on.""" + addon_env = self.addons_data.get_environment(self.addon) or {} + + return { + **addon_env, + 'TZ': self.config.timezone, + } + @property def volumes(self): """Generate volumes for mappings.""" @@ -89,7 +99,7 @@ def _run(self): network_mode=self.addons_data.get_network_mode(self.addon), ports=self.addons_data.get_ports(self.addon), devices=self.addons_data.get_devices(self.addon), - environment=self.addons_data.get_environment(self.addon), + environment=self.environment, volumes=self.volumes ) diff --git a/hassio/dock/homeassistant.py b/hassio/dock/homeassistant.py index 588a0b1dd42..f4c298f8b91 100644 --- a/hassio/dock/homeassistant.py +++ b/hassio/dock/homeassistant.py @@ -42,6 +42,7 @@ def _run(self): network_mode='host', environment={ 'HASSIO': self.config.api_endpoint, + 'TZ': self.config.timezone, }, volumes={ str(self.config.path_extern_config): diff --git a/hassio/tools.py b/hassio/tools.py index 7fc3562bb10..6eedce39a72 100644 --- a/hassio/tools.py +++ b/hassio/tools.py @@ -7,6 +7,8 @@ import aiohttp import async_timeout +import pytz +import voluptuous as vol from .const import URL_HASSIO_VERSION, URL_HASSIO_VERSION_BETA @@ -90,3 +92,16 @@ def read_json_file(jsonfile): """Read a json file and return a dict.""" with jsonfile.open('r') as cfile: return json.loads(cfile.read()) + + +def validate_timezone(timezone): + """Validate voluptuous timezone.""" + try: + pytz.timezone(timezone) + except pytz.exceptions.UnknownTimeZoneError: + raise vol.Invalid( + "Invalid time zone passed in. Valid options can be found here: " + "http://en.wikipedia.org/wiki/List_of_tz_database_time_zones") \ + from None + + return timezone diff --git a/setup.py b/setup.py index 14374be3a7a..8ffc0f50727 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ 'voluptuous', 'gitpython', 'pyotp', - 'pyqrcode' + 'pyqrcode', + 'pytz' ] )