diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 74d692efb945a..ec80cedbc3c64 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,7 +29,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -55,7 +55,7 @@ jobs: pip uninstall -y typing - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -82,7 +82,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -97,7 +97,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -126,7 +126,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -141,7 +141,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -170,7 +170,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -185,7 +185,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -236,7 +236,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -251,7 +251,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -283,7 +283,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -298,7 +298,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -330,7 +330,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -345,7 +345,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -374,7 +374,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -389,7 +389,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -421,7 +421,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -436,7 +436,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -476,7 +476,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -491,7 +491,7 @@ jobs: exit 1 - name: Restore pre-commit environment from cache id: cache-precommit - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: ${{ env.PRE_COMMIT_HOME }} key: | @@ -523,7 +523,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -555,7 +555,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore base Python virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -586,7 +586,7 @@ jobs: - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -627,7 +627,7 @@ jobs: - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -662,7 +662,7 @@ jobs: - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -699,7 +699,7 @@ jobs: - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- @@ -760,7 +760,7 @@ jobs: - name: Restore full Python ${{ matrix.python-version }} virtual environment id: cache-venv - uses: actions/cache@v2 + uses: actions/cache@v3.0.11 with: path: venv key: >- diff --git a/homeassistant/components/proxmoxve/__init__.py b/homeassistant/components/proxmoxve/__init__.py index 0919feb15e347..d87ff7c2716e4 100644 --- a/homeassistant/components/proxmoxve/__init__.py +++ b/homeassistant/components/proxmoxve/__init__.py @@ -26,6 +26,7 @@ CONF_NODES = "nodes" CONF_VMS = "vms" CONF_CONTAINERS = "containers" +CONF_STORAGE = "storage" DEFAULT_PORT = 8006 DEFAULT_REALM = "pam" @@ -58,6 +59,9 @@ vol.Optional(CONF_CONTAINERS, default=[]): [ cv.positive_int ], + vol.Optional(CONF_STORAGE, default=[]): [ + cv.string + ], } ) ], @@ -107,6 +111,9 @@ def setup(hass, config): hass.helpers.discovery.load_platform( "binary_sensor", DOMAIN, {"entries": config[DOMAIN]}, config ) + hass.helpers.discovery.load_platform( + "sensor", DOMAIN, {"entries": config[DOMAIN]}, config + ) return True return False @@ -117,6 +124,7 @@ class ProxmoxItemType(Enum): qemu = 0 lxc = 1 + storage = 2 class ProxmoxClient: diff --git a/homeassistant/components/proxmoxve/sensor.py b/homeassistant/components/proxmoxve/sensor.py new file mode 100644 index 0000000000000..09ab2c4a67dde --- /dev/null +++ b/homeassistant/components/proxmoxve/sensor.py @@ -0,0 +1,117 @@ +"""Sensor to read Proxmox VE data.""" +import logging + +from homeassistant.const import ATTR_ATTRIBUTION, CONF_HOST, CONF_PORT +from homeassistant.helpers.entity import Entity + +from . import CONF_NODES, CONF_STORAGE, PROXMOX_CLIENTS, ProxmoxItemType + +ATTRIBUTION = "Data provided by Proxmox VE" +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Set up the sensor platform.""" + + sensors = [] + + for entry in discovery_info["entries"]: + port = entry[CONF_PORT] + + for node in entry[CONF_NODES]: + for storage in node[CONF_STORAGE]: + sensors.append( + ProxmoxSensor( + hass.data[PROXMOX_CLIENTS][f"{entry[CONF_HOST]}:{port}"], + node["node"], + ProxmoxItemType.storage, + storage, + ) + ) + + add_entities(sensors, True) + + +class ProxmoxSensor(Entity): + """A binary sensor for reading Proxmox VE data.""" + + def __init__(self, proxmox_client, item_node, item_type, item_name): + """Initialize the binary sensor.""" + self._proxmox_client = proxmox_client + self._item_node = item_node + self._item_type = item_type + self._storagename = item_name + + self._name = None + self._maxdisk = None + self._usedisk = None + self._state = None + self._total = None + self._used = None + self._avail = None + self._content = None + self._type = None + + @property + def name(self): + """Return the name of the entity.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return "%" + + @property + def state(self): + """Return percent of storage used if storage is available.""" + return self._state + + @property + def device_state_attributes(self): + """Return device attributes of the entity.""" + return { + "node": self._item_node, + "storagename": self._storagename, + "type": self._type, + "gb_total": self._total, + "gb_used": self._used, + "gb_avail": self._avail, + "content": self._content, + ATTR_ATTRIBUTION: ATTRIBUTION, + } + + def update(self): + """Check if the storage exists.""" + item = self.poll_item() + + if item is None: + _LOGGER.warning("Failed to poll storage %s", self._storagename) + return + + self._state = round(item["used_fraction"] * 100, 1) + self._total = round(item["total"] / 1024 / 1024 / 1024, 1) + self._used = round(item["used"] / 1024 / 1024 / 1024, 1) + self._avail = round(item["avail"] / 1024 / 1024 / 1024, 1) + self._content = item["content"] + self._type = item["type"] + + def poll_item(self): + """Find the storage with the set name.""" + items = ( + self._proxmox_client.get_api_client() + .nodes(self._item_node) + .get(self._item_type.name) + ) + item = next( + (item for item in items if item["storage"] == str(self._storagename)), None + ) + + if item is None: + _LOGGER.warning("Couldn't find storage with the name %s", self._storagename) + return None + + if self._name is None: + self._name = f"{self._item_node} storage {self._storagename}" + + return item