This commit is contained in:
pvizeli 2017-04-11 17:34:14 +02:00 committed by Pascal Vizeli
parent 318ca828cc
commit 14500d3ac4
5 changed files with 82 additions and 18 deletions

View File

@ -10,7 +10,7 @@ from ..docker.addon import DockerAddon
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
class AddonsManager(object): class AddonManager(object):
"""Manage addons inside HassIO.""" """Manage addons inside HassIO."""
def __init__(self, config, loop, dock): def __init__(self, config, loop, dock):
@ -46,7 +46,7 @@ class AddonsManager(object):
return False return False
if self.addons.is_installed(addon): if self.addons.is_installed(addon):
_LOGGER.error("Addon %s is allready installed.", addon) _LOGGER.error("Addon %s is already installed.", addon)
return False return False
if not os.path.isdir(self.addons.path_data(addon)): if not os.path.isdir(self.addons.path_data(addon)):
@ -59,7 +59,6 @@ class AddonsManager(object):
version = version or self.addons.get_version(addon) version = version or self.addons.get_version(addon)
if not await addon_docker.install(version): if not await addon_docker.install(version):
_LOGGER.error("Can't install addon %s version %s.", addon, version)
return False return False
self.dockers[addon] = addon_docker self.dockers[addon] = addon_docker
@ -68,8 +67,8 @@ class AddonsManager(object):
async def uninstall_addon(self, addon): async def uninstall_addon(self, addon):
"""Remove a addon.""" """Remove a addon."""
if self.addons.is_installed(addon): if not self.addons.is_installed(addon):
_LOGGER.error("Addon %s is allready installed.", addon) _LOGGER.error("Addon %s is already uninstalled.", addon)
return False return False
if addon not in self.dockers: if addon not in self.dockers:
@ -77,7 +76,6 @@ class AddonsManager(object):
return False return False
if not await self.dockers[addon].remove(version): if not await self.dockers[addon].remove(version):
_LOGGER.error("Can't install addon %s.", addon)
return False return False
if os.path.isdir(self.addons.path_data(addon)): if os.path.isdir(self.addons.path_data(addon)):
@ -88,3 +86,29 @@ class AddonsManager(object):
self.dockers.pop(addon) self.dockers.pop(addon)
self.addons.set_uninstall_addon(addon) self.addons.set_uninstall_addon(addon)
return True return True
async def start_addon(self, addon):
"""Set options and start addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s.", addon)
return False
if not self.write_addon_options(addon):
_LOGGER.error("Can't write options for addon %s.", addon)
return False
if not await self.dockers[addon].run():
return False
return True
async def stop_addon(self, addon):
"""Stop addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s.", addon)
return False
if not await self.dockers[addon].stop():
return False
return True

View File

@ -1,7 +1,6 @@
"""Init file for HassIO addons.""" """Init file for HassIO addons."""
import logging import logging
import glob import glob
import json
import voluptuous as vol import voluptuous as vol
from voluptuous.humanize import humanize_error from voluptuous.humanize import humanize_error
@ -11,6 +10,7 @@ from ..const import (
ATTR_STARTUP, ATTR_BOOT, ATTR_MAP_SSL, ATTR_MAP_CONFIG, ATTR_MAP_DATA, ATTR_STARTUP, ATTR_BOOT, ATTR_MAP_SSL, ATTR_MAP_CONFIG, ATTR_MAP_DATA,
ATTR_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER, STARTUP_BEFORE, ATTR_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER, STARTUP_BEFORE,
BOOT_AUTO, BOOT_MANUAL, DOCKER_REPO) BOOT_AUTO, BOOT_MANUAL, DOCKER_REPO)
from ..tools import read_json_file, write_json_file
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -48,8 +48,7 @@ class AddonsConfig(Config):
for addon in glob.iglob(pattern): for addon in glob.iglob(pattern):
try: try:
with open(addon, 'r') as cfile: addon_config = read_json_file(addon)
addon_config = json.loads(cfile.read())
addon_config = SCHEMA_ADDON_CONFIG(addon_config) addon_config = SCHEMA_ADDON_CONFIG(addon_config)
self._addons_data[addon_config[ATTR_SLUG]] = addon_config self._addons_data[addon_config[ATTR_SLUG]] = addon_config
@ -76,7 +75,10 @@ class AddonsConfig(Config):
def set_install_addon(self, addon, version): def set_install_addon(self, addon, version):
"""Set addon as installed.""" """Set addon as installed."""
self._data[addon] = {ATTR_VERSION: version} self._data[addon] = {
ATTR_VERSION: version,
ATTR_OPTIONS: {}
}
self.save() self.save()
def set_uninstall_addon(self, addon, version): def set_uninstall_addon(self, addon, version):
@ -84,6 +86,13 @@ class AddonsConfig(Config):
self._data.pop(addon, None) self._data.pop(addon, None)
self.save() self.save()
def get_options(self, addon):
"""Return options with local changes."""
opt = self._addons_data[addon][ATTR_OPTIONS]
if addon in self._data:
opt.update(self._data[addon][ATTR_OPTIONS])
return opt
def get_image(self, addon): def get_image(self, addon):
"""Return name of addon docker image.""" """Return name of addon docker image."""
return "{}/{}-addon-{}".format( return "{}/{}-addon-{}".format(
@ -123,3 +132,12 @@ class AddonsConfig(Config):
"""Return addon data path external for docker.""" """Return addon data path external for docker."""
return "{}/{}".format(self.config.path_addons_data_docker, return "{}/{}".format(self.config.path_addons_data_docker,
self._addons_data[addon][ATTR_SLUG]) self._addons_data[addon][ATTR_SLUG])
def path_addon_options(self, addon):
"""Return path to addons options."""
return "{}/options.json".format(self.path_data(addon))
def write_addon_options(self, addon):
"""Return True if addon options is written to data."""
return write_json_file(
self.path_addon_options(addon), self.get_options(addon))

View File

@ -4,7 +4,9 @@ import logging
import os import os
from .const import FILE_HASSIO_CONFIG, HASSIO_SHARE from .const import FILE_HASSIO_CONFIG, HASSIO_SHARE
from .tools import fetch_current_versions, get_arch_from_image from .tools import (
fetch_current_versions, get_arch_from_image, write_json_file,
read_json_file)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -32,20 +34,15 @@ class Config(object):
# init or load data # init or load data
if os.path.isfile(self._filename): if os.path.isfile(self._filename):
try: try:
with open(self._filename, 'r') as cfile: self._data = read_json_file(self._filename)
self._data = json.loads(cfile.read())
except OSError: except OSError:
_LOGGER.warning("Can't read %s", self._filename) _LOGGER.warning("Can't read %s", self._filename)
def save(self): def save(self):
"""Store data to config file.""" """Store data to config file."""
try: if not write_json_file(self._filename, self._data)
with open(self._filename, 'w') as conf_file:
conf_file.write(json.dumps(self._data))
except OSError:
_LOGGER.exception("Can't store config in %s", self._filename) _LOGGER.exception("Can't store config in %s", self._filename)
return False return False
return True return True

View File

@ -6,6 +6,7 @@ import aiohttp
import docker import docker
from . import bootstrap from . import bootstrap
from .addons import AddonManager
from .api import RestAPI from .api import RestAPI
from .host_controll import HostControll from .host_controll import HostControll
from .const import SOCKET_DOCKER, RUN_UPDATE_INFO_TASKS from .const import SOCKET_DOCKER, RUN_UPDATE_INFO_TASKS
@ -38,6 +39,9 @@ class HassIO(object):
# init HostControll # init HostControll
self.host_controll = HostControll(self.loop) self.host_controll = HostControll(self.loop)
# init addon system
self.addon_manager = AddonManager(self.config, self.loop, self.dock)
async def setup(self): async def setup(self):
"""Setup HassIO orchestration.""" """Setup HassIO orchestration."""
# supervisor # supervisor
@ -69,6 +73,9 @@ class HassIO(object):
_LOGGER.info("No HomeAssistant docker found.") _LOGGER.info("No HomeAssistant docker found.")
await self._setup_homeassistant() await self._setup_homeassistant()
# Load addons
await self.addon_manager.prepare()
async def start(self): async def start(self):
"""Start HassIO orchestration.""" """Start HassIO orchestration."""
# start api # start api

View File

@ -1,5 +1,6 @@
"""Tools file for HassIO.""" """Tools file for HassIO."""
import asyncio import asyncio
import json
import logging import logging
import re import re
import socket import socket
@ -64,3 +65,20 @@ def get_local_ip(loop):
return socket.gethostbyname(socket.gethostname()) return socket.gethostbyname(socket.gethostname())
finally: finally:
sock.close() sock.close()
def write_json_file(jsonfile, data):
"""Write a json file."""
try:
with open(jsonfile, 'w') as conf_file:
conf_file.write(json.dumps(data))
except OSError:
return False
return True
def read_json_file(jsonfile):
"""Read a json file and return a dict."""
with open(jsonfile, 'r') as cfile:
return json.loads(cfile.read())