Files

126 lines
3.9 KiB
Python

"""Config flow for the LibreNMS integration."""
from collections.abc import Mapping
import logging
from typing import Any, override
from aiolibrenms import Librenms
from aiolibrenms.const import CONNECT_ERRORS
from aiolibrenms.exceptions import LibrenmsUnauthenticatedError
import voluptuous as vol
from yarl import URL
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import (
CONF_API_KEY,
CONF_HOST,
CONF_PORT,
CONF_SSL,
CONF_URL,
CONF_VERIFY_SSL,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.selector import (
TextSelector,
TextSelectorConfig,
TextSelectorType,
)
from .const import DEFAULT_VERIFY_SSL, DOMAIN
class InvalidUrl(HomeAssistantError):
"""Error to indicate invalid URL."""
_LOGGER = logging.getLogger(__name__)
STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_URL): TextSelector(
config=TextSelectorConfig(type=TextSelectorType.URL)
),
vol.Required(CONF_API_KEY): TextSelector(
config=TextSelectorConfig(type=TextSelectorType.PASSWORD)
),
vol.Required(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): bool,
}
)
def _parse_url(url: str) -> tuple[str, int, bool]:
"""Parse the URL and return host, port, and ssl."""
parsed_url = URL(url)
if (
(host := parsed_url.host) is None
or (port := parsed_url.port) is None
or (scheme := parsed_url.scheme) is None
):
raise InvalidUrl
return host, port, scheme == "https"
async def check_connection(
hass: HomeAssistant, host: str, port: int, ssl: bool, verify_ssl: bool, api_key: str
) -> None:
"""Test connection."""
session = async_get_clientsession(hass, verify_ssl)
lnms = Librenms(session, api_key, host, port, ssl)
await lnms.system.async_get_system_info()
class LibrenmsConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for LibreNMS."""
VERSION = 1
_name: str
_current_data: Mapping[str, Any]
@override
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
try:
(host, port, ssl) = _parse_url(user_input[CONF_URL])
except InvalidUrl:
errors[CONF_URL] = "invalid_url"
else:
self._async_abort_entries_match({CONF_HOST: host, CONF_PORT: port})
try:
await check_connection(
self.hass,
host,
port,
ssl,
user_input[CONF_VERIFY_SSL],
user_input[CONF_API_KEY],
)
except LibrenmsUnauthenticatedError:
errors["base"] = "invalid_auth"
except CONNECT_ERRORS:
errors["base"] = "cannot_connect"
except Exception:
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
return self.async_create_entry(
title=host,
data={
CONF_HOST: host,
CONF_PORT: port,
CONF_SSL: ssl,
CONF_VERIFY_SSL: user_input[CONF_VERIFY_SSL],
CONF_API_KEY: user_input[CONF_API_KEY],
},
)
return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
)