mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-08 09:46:29 +00:00
Add support for stats & code cleanup (#297)
* Add support for stats & code cleanup * Add more stats * Move code into own object * Add to API * Update API * Add error handling * fix lint * fix block io
This commit is contained in:
parent
e992b70f92
commit
eebe90bd14
39
API.md
39
API.md
@ -86,6 +86,19 @@ Reload addons/version.
|
|||||||
|
|
||||||
Output is the raw docker log.
|
Output is the raw docker log.
|
||||||
|
|
||||||
|
- GET `/supervisor/stats`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cpu_percent": 0.0,
|
||||||
|
"memory_usage": 283123,
|
||||||
|
"memory_limit": 329392,
|
||||||
|
"network_tx": 0,
|
||||||
|
"network_rx": 0,
|
||||||
|
"blk_read": 0,
|
||||||
|
"blk_write": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- GET `/security/info`
|
- GET `/security/info`
|
||||||
@ -334,6 +347,19 @@ Proxy to real home-assistant instance.
|
|||||||
|
|
||||||
Proxy to real websocket instance.
|
Proxy to real websocket instance.
|
||||||
|
|
||||||
|
- GET `/homeassistant/stats`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cpu_percent": 0.0,
|
||||||
|
"memory_usage": 283123,
|
||||||
|
"memory_limit": 329392,
|
||||||
|
"network_tx": 0,
|
||||||
|
"network_rx": 0,
|
||||||
|
"blk_read": 0,
|
||||||
|
"blk_write": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### RESTful for API addons
|
### RESTful for API addons
|
||||||
|
|
||||||
- GET `/addons`
|
- GET `/addons`
|
||||||
@ -452,6 +478,19 @@ Only supported for local build addons
|
|||||||
|
|
||||||
Write data to add-on stdin
|
Write data to add-on stdin
|
||||||
|
|
||||||
|
- GET `/addons/{addon}/stats`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cpu_percent": 0.0,
|
||||||
|
"memory_usage": 283123,
|
||||||
|
"memory_limit": 329392,
|
||||||
|
"network_tx": 0,
|
||||||
|
"network_rx": 0,
|
||||||
|
"blk_read": 0,
|
||||||
|
"blk_write": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Host Control
|
## Host Control
|
||||||
|
|
||||||
Communicate over UNIX socket with a host daemon.
|
Communicate over UNIX socket with a host daemon.
|
||||||
|
@ -596,6 +596,14 @@ class Addon(CoreSysAttributes):
|
|||||||
"""
|
"""
|
||||||
return self.instance.logs()
|
return self.instance.logs()
|
||||||
|
|
||||||
|
@check_installed
|
||||||
|
def stats(self):
|
||||||
|
"""Return stats of container.
|
||||||
|
|
||||||
|
Return a coroutine.
|
||||||
|
"""
|
||||||
|
return self.instance.stats()
|
||||||
|
|
||||||
@check_installed
|
@check_installed
|
||||||
async def rebuild(self):
|
async def rebuild(self):
|
||||||
"""Performe a rebuild of local build addon."""
|
"""Performe a rebuild of local build addon."""
|
||||||
|
@ -69,6 +69,7 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
|
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
|
||||||
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
|
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
|
||||||
|
self.webapp.router.add_get('/supervisor/stats', api_supervisor.stats)
|
||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
'/supervisor/update', api_supervisor.update)
|
'/supervisor/update', api_supervisor.update)
|
||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
@ -84,6 +85,7 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.router.add_get('/homeassistant/info', api_hass.info)
|
self.webapp.router.add_get('/homeassistant/info', api_hass.info)
|
||||||
self.webapp.router.add_get('/homeassistant/logs', api_hass.logs)
|
self.webapp.router.add_get('/homeassistant/logs', api_hass.logs)
|
||||||
|
self.webapp.router.add_get('/homeassistant/stats', api_hass.stats)
|
||||||
self.webapp.router.add_post('/homeassistant/options', api_hass.options)
|
self.webapp.router.add_post('/homeassistant/options', api_hass.options)
|
||||||
self.webapp.router.add_post('/homeassistant/update', api_hass.update)
|
self.webapp.router.add_post('/homeassistant/update', api_hass.update)
|
||||||
self.webapp.router.add_post('/homeassistant/restart', api_hass.restart)
|
self.webapp.router.add_post('/homeassistant/restart', api_hass.restart)
|
||||||
@ -114,7 +116,6 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.router.add_get('/addons', api_addons.list)
|
self.webapp.router.add_get('/addons', api_addons.list)
|
||||||
self.webapp.router.add_post('/addons/reload', api_addons.reload)
|
self.webapp.router.add_post('/addons/reload', api_addons.reload)
|
||||||
|
|
||||||
self.webapp.router.add_get('/addons/{addon}/info', api_addons.info)
|
self.webapp.router.add_get('/addons/{addon}/info', api_addons.info)
|
||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
'/addons/{addon}/install', api_addons.install)
|
'/addons/{addon}/install', api_addons.install)
|
||||||
@ -135,6 +136,7 @@ class RestAPI(CoreSysAttributes):
|
|||||||
self.webapp.router.add_get(
|
self.webapp.router.add_get(
|
||||||
'/addons/{addon}/changelog', api_addons.changelog)
|
'/addons/{addon}/changelog', api_addons.changelog)
|
||||||
self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin)
|
self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin)
|
||||||
|
self.webapp.router.add_get('/addons/{addon}/stats', api_addons.stats)
|
||||||
|
|
||||||
def _register_security(self):
|
def _register_security(self):
|
||||||
"""Register security function."""
|
"""Register security function."""
|
||||||
|
@ -15,6 +15,8 @@ from ..const import (
|
|||||||
ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API,
|
ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API,
|
||||||
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, BOOT_AUTO, BOOT_MANUAL,
|
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, BOOT_AUTO, BOOT_MANUAL,
|
||||||
ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, ATTR_LONG_DESCRIPTION,
|
ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, ATTR_LONG_DESCRIPTION,
|
||||||
|
ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX,
|
||||||
|
ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE,
|
||||||
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
|
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..validate import DOCKER_PORTS
|
from ..validate import DOCKER_PORTS
|
||||||
@ -158,6 +160,25 @@ class APIAddons(CoreSysAttributes):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@api_process
|
||||||
|
async def stats(self, request):
|
||||||
|
"""Return resource information."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
stats = await addon.stats()
|
||||||
|
|
||||||
|
if not stats:
|
||||||
|
raise RuntimeError("No stats available")
|
||||||
|
|
||||||
|
return {
|
||||||
|
ATTR_CPU_PERCENT: stats.cpu_percent,
|
||||||
|
ATTR_MEMORY_USAGE: stats.memory_usage,
|
||||||
|
ATTR_MEMORY_LIMIT: stats.memory_limit,
|
||||||
|
ATTR_NETWORK_RX: stats.network_rx,
|
||||||
|
ATTR_NETWORK_TX: stats.network_tx,
|
||||||
|
ATTR_BLK_READ: stats.blk_read,
|
||||||
|
ATTR_BLK_WRITE: stats.blk_write,
|
||||||
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def install(self, request):
|
def install(self, request):
|
||||||
"""Install addon."""
|
"""Install addon."""
|
||||||
|
@ -7,7 +7,9 @@ import voluptuous as vol
|
|||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_IMAGE, ATTR_CUSTOM, ATTR_BOOT,
|
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_IMAGE, ATTR_CUSTOM, ATTR_BOOT,
|
||||||
ATTR_PORT, ATTR_PASSWORD, ATTR_SSL, ATTR_WATCHDOG, CONTENT_TYPE_BINARY)
|
ATTR_PORT, ATTR_PASSWORD, ATTR_SSL, ATTR_WATCHDOG, ATTR_CPU_PERCENT,
|
||||||
|
ATTR_MEMORY_USAGE, ATTR_MEMORY_LIMIT, ATTR_NETWORK_RX, ATTR_NETWORK_TX,
|
||||||
|
ATTR_BLK_READ, ATTR_BLK_WRITE, CONTENT_TYPE_BINARY)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..validate import NETWORK_PORT
|
from ..validate import NETWORK_PORT
|
||||||
|
|
||||||
@ -76,6 +78,23 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
self._homeassistant.save()
|
self._homeassistant.save()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@api_process
|
||||||
|
async def stats(self, request):
|
||||||
|
"""Return resource information."""
|
||||||
|
stats = await self._homeassistant.stats()
|
||||||
|
if not stats:
|
||||||
|
raise RuntimeError("No stats available")
|
||||||
|
|
||||||
|
return {
|
||||||
|
ATTR_CPU_PERCENT: stats.cpu_percent,
|
||||||
|
ATTR_MEMORY_USAGE: stats.memory_usage,
|
||||||
|
ATTR_MEMORY_LIMIT: stats.memory_limit,
|
||||||
|
ATTR_NETWORK_RX: stats.network_rx,
|
||||||
|
ATTR_NETWORK_TX: stats.network_tx,
|
||||||
|
ATTR_BLK_READ: stats.blk_read,
|
||||||
|
ATTR_BLK_WRITE: stats.blk_write,
|
||||||
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def update(self, request):
|
async def update(self, request):
|
||||||
"""Update homeassistant."""
|
"""Update homeassistant."""
|
||||||
|
@ -9,7 +9,9 @@ from ..const import (
|
|||||||
ATTR_ADDONS, ATTR_VERSION, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL, ATTR_ARCH,
|
ATTR_ADDONS, ATTR_VERSION, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL, ATTR_ARCH,
|
||||||
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_LOGO, ATTR_REPOSITORY,
|
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_LOGO, ATTR_REPOSITORY,
|
||||||
ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED, ATTR_TIMEZONE,
|
ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED, ATTR_TIMEZONE,
|
||||||
ATTR_STATE, ATTR_WAIT_BOOT, CONTENT_TYPE_BINARY)
|
ATTR_STATE, ATTR_WAIT_BOOT, ATTR_CPU_PERCENT, ATTR_MEMORY_USAGE,
|
||||||
|
ATTR_MEMORY_LIMIT, ATTR_NETWORK_RX, ATTR_NETWORK_TX, ATTR_BLK_READ,
|
||||||
|
ATTR_BLK_WRITE, CONTENT_TYPE_BINARY)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..validate import validate_timezone, WAIT_BOOT
|
from ..validate import validate_timezone, WAIT_BOOT
|
||||||
|
|
||||||
@ -86,6 +88,23 @@ class APISupervisor(CoreSysAttributes):
|
|||||||
self._config.save()
|
self._config.save()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@api_process
|
||||||
|
async def stats(self, request):
|
||||||
|
"""Return resource information."""
|
||||||
|
stats = await self._supervisor.stats()
|
||||||
|
if not stats:
|
||||||
|
raise RuntimeError("No stats available")
|
||||||
|
|
||||||
|
return {
|
||||||
|
ATTR_CPU_PERCENT: stats.cpu_percent,
|
||||||
|
ATTR_MEMORY_USAGE: stats.memory_usage,
|
||||||
|
ATTR_MEMORY_LIMIT: stats.memory_limit,
|
||||||
|
ATTR_NETWORK_RX: stats.network_rx,
|
||||||
|
ATTR_NETWORK_TX: stats.network_tx,
|
||||||
|
ATTR_BLK_READ: stats.blk_read,
|
||||||
|
ATTR_BLK_WRITE: stats.blk_write,
|
||||||
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def update(self, request):
|
async def update(self, request):
|
||||||
"""Update supervisor OS."""
|
"""Update supervisor OS."""
|
||||||
|
@ -128,6 +128,13 @@ ATTR_SQUASH = 'squash'
|
|||||||
ATTR_GPIO = 'gpio'
|
ATTR_GPIO = 'gpio'
|
||||||
ATTR_LEGACY = 'legacy'
|
ATTR_LEGACY = 'legacy'
|
||||||
ATTR_ADDONS_CUSTOM_LIST = 'addons_custom_list'
|
ATTR_ADDONS_CUSTOM_LIST = 'addons_custom_list'
|
||||||
|
ATTR_CPU_PERCENT = 'cpu_percent'
|
||||||
|
ATTR_NETWORK_RX = 'network_rx'
|
||||||
|
ATTR_NETWORK_TX = 'network_tx'
|
||||||
|
ATTR_MEMORY_LIMIT = 'memory_limit'
|
||||||
|
ATTR_MEMORY_USAGE = 'memory_usage'
|
||||||
|
ATTR_BLK_READ = 'blk_read'
|
||||||
|
ATTR_BLK_WRITE = 'blk_write'
|
||||||
|
|
||||||
STARTUP_INITIALIZE = 'initialize'
|
STARTUP_INITIALIZE = 'initialize'
|
||||||
STARTUP_SYSTEM = 'system'
|
STARTUP_SYSTEM = 'system'
|
||||||
|
@ -4,10 +4,10 @@ import aiohttp
|
|||||||
|
|
||||||
from .config import CoreConfig
|
from .config import CoreConfig
|
||||||
from .docker import DockerAPI
|
from .docker import DockerAPI
|
||||||
from .dns import DNSForward
|
from .misc.dns import DNSForward
|
||||||
from .hardware import Hardware
|
from .misc.hardware import Hardware
|
||||||
from .host_control import HostControl
|
from .misc.host_control import HostControl
|
||||||
from .scheduler import Scheduler
|
from .misc.scheduler import Scheduler
|
||||||
|
|
||||||
|
|
||||||
class CoreSys(object):
|
class CoreSys(object):
|
||||||
|
@ -6,6 +6,7 @@ import logging
|
|||||||
import docker
|
import docker
|
||||||
|
|
||||||
from .utils import docker_process
|
from .utils import docker_process
|
||||||
|
from .stats import DockerStats
|
||||||
from ..const import LABEL_VERSION, LABEL_ARCH
|
from ..const import LABEL_VERSION, LABEL_ARCH
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
@ -325,3 +326,24 @@ class DockerInterface(CoreSysAttributes):
|
|||||||
Need run inside executor.
|
Need run inside executor.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def stats(self):
|
||||||
|
"""Read and return stats from container."""
|
||||||
|
return self._loop.run_in_executor(None, self._stats)
|
||||||
|
|
||||||
|
def _stats(self):
|
||||||
|
"""Create a temporary container and run command.
|
||||||
|
|
||||||
|
Need run inside executor.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
container = self._docker.containers.get(self.name)
|
||||||
|
except docker.errors.DockerException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
stats = container.stats(stream=False)
|
||||||
|
return DockerStats(stats)
|
||||||
|
except docker.errors.DockerException as err:
|
||||||
|
_LOGGER.error("Can't read stats from %s: %s", self.name, err)
|
||||||
|
return None
|
||||||
|
90
hassio/docker/stats.py
Normal file
90
hassio/docker/stats.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
"""Calc & represent docker stats data."""
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
|
|
||||||
|
class DockerStats(object):
|
||||||
|
"""Hold stats data from container inside."""
|
||||||
|
|
||||||
|
def __init__(self, stats):
|
||||||
|
"""Initialize docker stats."""
|
||||||
|
self._cpu = 0.0
|
||||||
|
self._network_rx = 0
|
||||||
|
self._network_tx = 0
|
||||||
|
self._blk_read = 0
|
||||||
|
self._blk_write = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._memory_usage = stats['memory_stats']['usage']
|
||||||
|
self._memory_limit = stats['memory_stats']['limit']
|
||||||
|
except KeyError:
|
||||||
|
self._memory_usage = 0
|
||||||
|
self._memory_limit = 0
|
||||||
|
|
||||||
|
with suppress(KeyError):
|
||||||
|
self._calc_cpu_percent(stats)
|
||||||
|
|
||||||
|
with suppress(KeyError):
|
||||||
|
self._calc_network(stats['networks'])
|
||||||
|
|
||||||
|
with suppress(KeyError):
|
||||||
|
self._calc_block_io(stats['blkio_stats'])
|
||||||
|
|
||||||
|
def _calc_cpu_percent(self, stats):
|
||||||
|
"""Calculate CPU percent."""
|
||||||
|
cpu_delta = stats['cpu_stats']['cpu_usage']['total_usage'] - \
|
||||||
|
stats['precpu_stats']['cpu_usage']['total_usage']
|
||||||
|
system_delta = stats['cpu_stats']['system_cpu_usage'] - \
|
||||||
|
stats['precpu_stats']['system_cpu_usage']
|
||||||
|
|
||||||
|
if system_delta > 0.0 and cpu_delta > 0.0:
|
||||||
|
self._cpu = (cpu_delta / system_delta) * \
|
||||||
|
len(stats['cpu_stats']['cpu_usage']['percpu_usage']) * 100.0
|
||||||
|
|
||||||
|
def _calc_network(self, networks):
|
||||||
|
"""Calculate Network IO stats."""
|
||||||
|
for _, stats in networks.items():
|
||||||
|
self._network_rx += stats['rx_bytes']
|
||||||
|
self._network_tx += stats['tx_bytes']
|
||||||
|
|
||||||
|
def _calc_block_io(self, blkio):
|
||||||
|
"""Calculate block IO stats."""
|
||||||
|
for stats in blkio['io_service_bytes_recursive']:
|
||||||
|
if stats['op'] == 'Read':
|
||||||
|
self._blk_read += stats['value']
|
||||||
|
elif stats['op'] == 'Write':
|
||||||
|
self._blk_write += stats['value']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_percent(self):
|
||||||
|
"""Return CPU percent."""
|
||||||
|
return self._cpu
|
||||||
|
|
||||||
|
@property
|
||||||
|
def memory_usage(self):
|
||||||
|
"""Return memory usage."""
|
||||||
|
return self._memory_usage
|
||||||
|
|
||||||
|
@property
|
||||||
|
def memory_limit(self):
|
||||||
|
"""Return memory limit."""
|
||||||
|
return self._memory_limit
|
||||||
|
|
||||||
|
@property
|
||||||
|
def network_rx(self):
|
||||||
|
"""Return network rx stats."""
|
||||||
|
return self._network_rx
|
||||||
|
|
||||||
|
@property
|
||||||
|
def network_tx(self):
|
||||||
|
"""Return network rx stats."""
|
||||||
|
return self._network_tx
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blk_read(self):
|
||||||
|
"""Return block IO read stats."""
|
||||||
|
return self._blk_read
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blk_write(self):
|
||||||
|
"""Return block IO write stats."""
|
||||||
|
return self._blk_write
|
@ -219,6 +219,13 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
"""
|
"""
|
||||||
return self.instance.logs()
|
return self.instance.logs()
|
||||||
|
|
||||||
|
def stats(self):
|
||||||
|
"""Return stats of HomeAssistant.
|
||||||
|
|
||||||
|
Return a coroutine.
|
||||||
|
"""
|
||||||
|
return self.instance.stats()
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
"""Return True if docker container is running.
|
"""Return True if docker container is running.
|
||||||
|
|
||||||
|
1
hassio/misc/__init__.py
Normal file
1
hassio/misc/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Special object and tools for Hass.io."""
|
@ -6,7 +6,7 @@ import re
|
|||||||
|
|
||||||
import pyudev
|
import pyudev
|
||||||
|
|
||||||
from .const import ATTR_NAME, ATTR_TYPE, ATTR_DEVICES
|
from ..const import ATTR_NAME, ATTR_TYPE, ATTR_DEVICES
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
@ -5,7 +5,7 @@ import logging
|
|||||||
|
|
||||||
import async_timeout
|
import async_timeout
|
||||||
|
|
||||||
from .const import (
|
from ..const import (
|
||||||
SOCKET_HC, ATTR_LAST_VERSION, ATTR_VERSION, ATTR_TYPE, ATTR_FEATURES,
|
SOCKET_HC, ATTR_LAST_VERSION, ATTR_VERSION, ATTR_TYPE, ATTR_FEATURES,
|
||||||
ATTR_HOSTNAME, ATTR_OS)
|
ATTR_HOSTNAME, ATTR_OS)
|
||||||
|
|
@ -68,3 +68,10 @@ class Supervisor(CoreSysAttributes):
|
|||||||
Return a coroutine.
|
Return a coroutine.
|
||||||
"""
|
"""
|
||||||
return self.instance.logs()
|
return self.instance.logs()
|
||||||
|
|
||||||
|
def stats(self):
|
||||||
|
"""Return stats of Supervisor.
|
||||||
|
|
||||||
|
Return a coroutine.
|
||||||
|
"""
|
||||||
|
return self.instance.stats()
|
||||||
|
5
setup.py
5
setup.py
@ -31,10 +31,11 @@ setup(
|
|||||||
platforms='any',
|
platforms='any',
|
||||||
packages=[
|
packages=[
|
||||||
'hassio',
|
'hassio',
|
||||||
'hassio.utils',
|
|
||||||
'hassio.docker',
|
'hassio.docker',
|
||||||
'hassio.api',
|
|
||||||
'hassio.addons',
|
'hassio.addons',
|
||||||
|
'hassio.api',
|
||||||
|
'hassio.misc',
|
||||||
|
'hassio.utils',
|
||||||
'hassio.snapshots'
|
'hassio.snapshots'
|
||||||
],
|
],
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user