Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
ualex73 committed Jun 14, 2020
0 parents commit a2726c0
Show file tree
Hide file tree
Showing 9 changed files with 1,518 additions and 0 deletions.
95 changes: 95 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Custom Monitor Docker component for Home Assistant

[![maintainer](https://img.shields.io/badge/maintainer-ualex73-blue.svg?style=for-the-badge)](https://github.com/ualex73)

## About

This repository contains the Monitor Docker component I developed for monitor my Docker environment from [Home-Assistant](https://www.home-assistant.io). It is inspired by the Sander Huismans [Docker Monitor](https://github.com/Sanderhuisman/docker_monitor), where I switched mainly from threads to asyncio and put my own wishes/functionality in. Feel free to use the component and report bugs if you find them. If you want to contribute, please report a bug or pull request and I will reply as soon as possible.

## Monitor Docker

The Monitor Docker allows you to monitor Docker and container statistics and turn on/off containers. It can connected to the Docker daemon locally or remotely. When Home Assistant is used within a Docker container, the Docker daemon should be mounted as follows `-v /var/run/docker.sock:/var/run/docker.sock`.

## Installation

### Manual
- Copy directory `custom_components/monitor_docker` to your `<config dir>/custom_components` directory.
- Configure with config below.
- Restart Home-Assistant.

### Configuration

To use the `monitor_docker` in your installation, add the following to your `configuration.yaml` file:

```yaml
# Example configuration.yaml entry
monitor_docker:
- name: Docker
containers:
- appdaemon
- db-dsmr
- db-hass
- deconz
- dsmr
- hass
- influxdb
- mosquitto
- nodered
- unifi
rename:
appdaemon: AppDaemon
db-dsmr: "Database DSMR-Reader"
db-hass: Database Home Assistant
deconz: DeCONZ
domotiga: DomotiGa
dsmr: "DSMR-Reader"
hass: Home Assistant
influxdb: InfluxDB
mosquitto: Mosquitto
nodered: "Node-RED"
unifi: UniFi
sensorname: "{name}"
switchname: "{name}"
monitored_conditions:
- version
- containers_active
- containers_total
- status
- memory
```
#### Configuration variables
| Parameter | Type | Description |
| -------------------- | ------------------------ | --------------------------------------------------------------------- |
| name | string (Required) | Client name of Docker daemon. Defaults to `Docker`. |
| url | string (Optional) | Host URL of Docker daemon. Defaults to `unix://var/run/docker.sock`. |
| scan_interval | time_period (Optional) | Update interval. Defaults to 10 seconds. |
| containers | list (Optional) | Array of containers to monitor. Defaults to all containers. |
| monitored_conditions | list (Optional) | Array of conditions to be monitored. Defaults to all conditions. |
| rename | dictionary (Optional) | Dictionary of containers to rename. Default no renaming. |
| sensorname | string (Optional) | Sensor string to format the name used in Home Assistant. Defaults to `Docker {name} {sensorname}`, where `{name}` is the container name and `{sensorname}` is e.g. Memory, Status, Network speed Up |
| switchname | string (optional) | Switch string to format the name used in Home Assistant. Defaults to `Docker {name}`, where `{name}` is the container name. |

| Monitored Conditions | Description | Unit |
| --------------------------------- | ------------------------------- | ----- |
| version | Docker version | - |
| containers_total | Total number of containers | - |
| containers_running | Number of running containers | - |
| containers_cpu_percentage | CPU Usage | % |
| containers_memory | Memory usage | MB |
| containers_memory_percentage | Memory usage | % |
| status | Container status | - |
| uptime | Container start time | - |
| image | Container image | - |
| cpu_percentage | CPU usage | % |
| memory | Memory usage | MB |
| memory_percentage | Memory usage | % |
| network_speed_up | Network speed upstream | kB/s |
| network_speed_down | Network speed downstream | kB/s |
| network_total_up | Network total upstream | MB |
| network_total_down | Network total downstream | MB |

## Credits

* [Sanderhuisman](https://github.com/Sanderhuisman/docker_monitor)
102 changes: 102 additions & 0 deletions custom_components/monitor_docker/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Monitor Docker main component."""

import asyncio
import logging
import threading
import voluptuous as vol

from datetime import timedelta

import homeassistant.helpers.config_validation as cv

from homeassistant.helpers.discovery import load_platform

from .helpers import DockerAPI, DockerContainerAPI

from homeassistant.const import (
CONF_MONITORED_CONDITIONS,
CONF_NAME,
CONF_SCAN_INTERVAL,
CONF_URL,
EVENT_HOMEASSISTANT_STOP,
)

from .const import (
API,
CONF_CONTAINERS,
CONF_RENAME,
CONF_SENSORNAME,
CONF_SWITCHNAME,
CONFIG,
DOMAIN,
DEFAULT_NAME,
DEFAULT_SENSORNAME,
DEFAULT_SWITCHNAME,
MONITORED_CONDITIONS_LIST,
)

_LOGGER = logging.getLogger(__name__)

DEFAULT_SCAN_INTERVAL = timedelta(seconds=10)

DOCKER_SCHEMA = vol.Schema(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_URL, default=None): vol.Any(cv.string, None),
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): cv.time_period,
vol.Optional(
CONF_MONITORED_CONDITIONS, default=MONITORED_CONDITIONS_LIST
): vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS_LIST)]),
vol.Optional(CONF_CONTAINERS, default=[]): cv.ensure_list,
vol.Optional(CONF_RENAME, default={}): dict,
vol.Optional(CONF_SENSORNAME, default=DEFAULT_SENSORNAME): cv.string,
vol.Optional(CONF_SWITCHNAME, default=DEFAULT_SWITCHNAME): cv.string,
}
)

CONFIG_SCHEMA = vol.Schema(
{DOMAIN: vol.All(cv.ensure_list, [vol.Any(DOCKER_SCHEMA)])}, extra=vol.ALLOW_EXTRA
)

#################################################################
async def async_setup(hass, config):
"""Setup the Monitor Docker platform."""

def RunDocker(hass, entry):
"""Wrapper function for a separated thread."""

# Create out asyncio loop, because we are already inside
# a def (not main) we need to do create/set
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

# Create docker instance, it will have asyncio threads
hass.data[DOMAIN][entry[CONF_NAME]] = {}
hass.data[DOMAIN][entry[CONF_NAME]][CONFIG] = entry
hass.data[DOMAIN][entry[CONF_NAME]][API] = DockerAPI(hass, entry)

# _LOGGER.error("load_platform switch")
# load_platform(self._hass, "switch", DOMAIN, self._config, self._config)

# Now run forever in this separated thread
loop.run_forever()

# Create domain monitor_docker data variable
hass.data[DOMAIN] = {}

# Now go through all possible entries, we support 1 or more docker hosts (untested)
for entry in config[DOMAIN]:
if entry[CONF_NAME] in hass.data[DOMAIN]:
_LOGGER.error(
"Instance %s is duplicate, please assign an unique name",
entry[CONF_NAME],
)
return False

# Each docker hosts runs in its own thread. We need to pass hass too, for the load_platform
thread = threading.Thread(
target=RunDocker, kwargs={"hass": hass, "entry": entry}
)
thread.start()

return True
90 changes: 90 additions & 0 deletions custom_components/monitor_docker/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""Define constants for the Monitor Docker component."""

DOMAIN = "monitor_docker"
API = "api"
CONFIG = "config"
CONTAINER = "container"

CONF_CONTAINERS = "containers"
CONF_RENAME = "rename"
CONF_SENSORNAME = "sensorname"
CONF_SWITCHNAME = "switchname"

DEFAULT_NAME = "Docker"
DEFAULT_SENSORNAME = "Docker {name} {sensorname}"
DEFAULT_SWITCHNAME = "Docker {name}"

COMPONENTS = ["sensor", "switch"]

PRECISION = 2

DOCKER_INFO_VERSION = "version"
DOCKER_INFO_CONTAINER_RUNNING = "containers_running"
DOCKER_INFO_CONTAINER_TOTAL = "containers_total"
DOCKER_STATS_CPU_PERCENTAGE = "containers_cpu_percentage"
DOCKER_STATS_MEMORY = "containers_memory"
DOCKER_STATS_MEMORY_PERCENTAGE = "containers_memory_percentage"

CONTAINER_INFO_STATE = "state"
CONTAINER_INFO_STATUS = "status"
CONTAINER_INFO_NETWORKMODE = "networkmode"
CONTAINER_INFO_UPTIME = "uptime"
CONTAINER_INFO_IMAGE = "image"
CONTAINER_STATS_CPU_PERCENTAGE = "cpu_percentage"
CONTAINER_STATS_MEMORY = "memory"
CONTAINER_STATS_MEMORY_PERCENTAGE = "memory_percentage"
CONTAINER_STATS_NETWORK_SPEED_UP = "network_speed_up"
CONTAINER_STATS_NETWORK_SPEED_DOWN = "network_speed_down"
CONTAINER_STATS_NETWORK_TOTAL_UP = "network_total_up"
CONTAINER_STATS_NETWORK_TOTAL_DOWN = "network_total_down"

DOCKER_MONITOR_LIST = {
DOCKER_INFO_VERSION: ["Version", None, "mdi:information-outline", None],
DOCKER_INFO_CONTAINER_RUNNING: ["Containers Running", None, "mdi:docker", None],
DOCKER_INFO_CONTAINER_TOTAL: ["Containers Total", None, "mdi:docker", None],
DOCKER_STATS_CPU_PERCENTAGE: ["CPU", "%", "mdi:chip", None],
DOCKER_STATS_MEMORY: ["Memory", "MB", "mdi:memory", None],
DOCKER_STATS_MEMORY_PERCENTAGE: ["Memory (percent)", "%", "mdi:memory", None],
}

CONTAINER_MONITOR_LIST = {
CONTAINER_INFO_STATE: ["State", None, "mdi:checkbox-marked-circle-outline", None],
CONTAINER_INFO_STATUS: ["Status", None, "mdi:checkbox-marked-circle-outline", None],
CONTAINER_INFO_UPTIME: ["Up Time", "", "mdi:clock", "timestamp"],
CONTAINER_INFO_IMAGE: ["Image", None, "mdi:information-outline", None],
CONTAINER_STATS_CPU_PERCENTAGE: ["CPU", "%", "mdi:chip", None],
CONTAINER_STATS_MEMORY: ["Memory", "MB", "mdi:memory", None],
CONTAINER_STATS_MEMORY_PERCENTAGE: ["Memory (percent)", "%", "mdi:memory", None],
CONTAINER_STATS_NETWORK_SPEED_UP: ["Network speed Up", "kB/s", "mdi:upload", None],
CONTAINER_STATS_NETWORK_SPEED_DOWN: [
"Network speed Down",
"kB/s",
"mdi:download",
None,
],
CONTAINER_STATS_NETWORK_TOTAL_UP: ["Network total Up", "MB", "mdi:upload", None],
CONTAINER_STATS_NETWORK_TOTAL_DOWN: [
"Network total Down",
"MB",
"mdi:download",
None,
],
}

CONTAINER_MONITOR_NETWORK_LIST = [
CONTAINER_STATS_NETWORK_SPEED_UP,
CONTAINER_STATS_NETWORK_SPEED_DOWN,
CONTAINER_STATS_NETWORK_TOTAL_UP,
CONTAINER_STATS_NETWORK_TOTAL_DOWN,
]

MONITORED_CONDITIONS_LIST = list(DOCKER_MONITOR_LIST.keys()) + list(
CONTAINER_MONITOR_LIST.keys()
)

ATTR_MEMORY_LIMIT = "Memory_limit"
ATTR_ONLINE_CPUS = "Online_CPUs"
ATTR_VERSION_ARCH = "Architecture"
ATTR_VERSION_KERNEL = "Kernel"
ATTR_VERSION_OS = "OS"
ATTR_VERSION_OS_TYPE = "OS_Type"
Loading

0 comments on commit a2726c0

Please sign in to comment.