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__)
class AddonsManager(object):
class AddonManager(object):
"""Manage addons inside HassIO."""
def __init__(self, config, loop, dock):
@ -46,7 +46,7 @@ class AddonsManager(object):
return False
if self.addons.is_installed(addon):
_LOGGER.error("Addon %s is allready installed.", addon)
_LOGGER.error("Addon %s is already installed.", addon)
return False
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)
if not await addon_docker.install(version):
_LOGGER.error("Can't install addon %s version %s.", addon, version)
return False
self.dockers[addon] = addon_docker
@ -68,8 +67,8 @@ class AddonsManager(object):
async def uninstall_addon(self, addon):
"""Remove a addon."""
if self.addons.is_installed(addon):
_LOGGER.error("Addon %s is allready installed.", addon)
if not self.addons.is_installed(addon):
_LOGGER.error("Addon %s is already uninstalled.", addon)
return False
if addon not in self.dockers:
@ -77,7 +76,6 @@ class AddonsManager(object):
return False
if not await self.dockers[addon].remove(version):
_LOGGER.error("Can't install addon %s.", addon)
return False
if os.path.isdir(self.addons.path_data(addon)):
@ -88,3 +86,29 @@ class AddonsManager(object):
self.dockers.pop(addon)
self.addons.set_uninstall_addon(addon)
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."""
import logging
import glob
import json
import voluptuous as vol
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_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER, STARTUP_BEFORE,
BOOT_AUTO, BOOT_MANUAL, DOCKER_REPO)
from ..tools import read_json_file, write_json_file
_LOGGER = logging.getLogger(__name__)
@ -48,8 +48,7 @@ class AddonsConfig(Config):
for addon in glob.iglob(pattern):
try:
with open(addon, 'r') as cfile:
addon_config = json.loads(cfile.read())
addon_config = read_json_file(addon)
addon_config = SCHEMA_ADDON_CONFIG(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):
"""Set addon as installed."""
self._data[addon] = {ATTR_VERSION: version}
self._data[addon] = {
ATTR_VERSION: version,
ATTR_OPTIONS: {}
}
self.save()
def set_uninstall_addon(self, addon, version):
@ -84,6 +86,13 @@ class AddonsConfig(Config):
self._data.pop(addon, None)
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):
"""Return name of addon docker image."""
return "{}/{}-addon-{}".format(
@ -123,3 +132,12 @@ class AddonsConfig(Config):
"""Return addon data path external for docker."""
return "{}/{}".format(self.config.path_addons_data_docker,
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
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__)
@ -32,20 +34,15 @@ class Config(object):
# init or load data
if os.path.isfile(self._filename):
try:
with open(self._filename, 'r') as cfile:
self._data = json.loads(cfile.read())
self._data = read_json_file(self._filename)
except OSError:
_LOGGER.warning("Can't read %s", self._filename)
def save(self):
"""Store data to config file."""
try:
with open(self._filename, 'w') as conf_file:
conf_file.write(json.dumps(self._data))
except OSError:
if not write_json_file(self._filename, self._data)
_LOGGER.exception("Can't store config in %s", self._filename)
return False
return True

View File

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

View File

@ -1,5 +1,6 @@
"""Tools file for HassIO."""
import asyncio
import json
import logging
import re
import socket
@ -64,3 +65,20 @@ def get_local_ip(loop):
return socket.gethostbyname(socket.gethostname())
finally:
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())