mirror of
https://github.com/home-assistant/core.git
synced 2026-08-31 18:24:50 -05:00
Improve ProxmoxVE config flow preparing bug fixing (#169682)
Co-authored-by: Erwin Douna <e.douna@gmail.com>
This commit is contained in:
committed by
Paulus Schoutsen
co-authored by
Erwin Douna
parent
9e357e7e5a
commit
ce4fc9e880
@@ -97,6 +97,19 @@ def _get_nodes_data(data: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
verify_ssl=data.get(CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL),
|
||||
**auth_kwargs,
|
||||
)
|
||||
except AuthenticationError as err:
|
||||
raise ProxmoxAuthenticationError from err
|
||||
except SSLError as err:
|
||||
raise ProxmoxSSLError from err
|
||||
except ConnectTimeout as err:
|
||||
raise ProxmoxConnectTimeout from err
|
||||
except ResourceException as err:
|
||||
_LOGGER.debug("Error during Proxmox client initialisation", exc_info=True)
|
||||
raise ProxmoxInitFailed from err
|
||||
except requests.exceptions.ConnectionError as err:
|
||||
raise ProxmoxConnectionError from err
|
||||
|
||||
try:
|
||||
nodes = client.nodes.get()
|
||||
except AuthenticationError as err:
|
||||
raise ProxmoxAuthenticationError from err
|
||||
@@ -105,6 +118,7 @@ def _get_nodes_data(data: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
except ConnectTimeout as err:
|
||||
raise ProxmoxConnectTimeout from err
|
||||
except ResourceException as err:
|
||||
_LOGGER.debug("Error fetching nodes", exc_info=True)
|
||||
raise ProxmoxNoNodesFound from err
|
||||
except requests.exceptions.ConnectionError as err:
|
||||
raise ProxmoxConnectionError from err
|
||||
@@ -115,7 +129,10 @@ def _get_nodes_data(data: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
vms = client.nodes(node["node"]).qemu.get()
|
||||
containers = client.nodes(node["node"]).lxc.get()
|
||||
except ResourceException as err:
|
||||
raise ProxmoxNoNodesFound from err
|
||||
_LOGGER.debug(
|
||||
"Error fetching VMs/LXC for node %s", node["node"], exc_info=True
|
||||
)
|
||||
raise ProxmoxNoVMLXCFound from err
|
||||
except requests.exceptions.ConnectionError as err:
|
||||
raise ProxmoxConnectionError from err
|
||||
|
||||
@@ -298,9 +315,15 @@ class ProxmoxveConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
except ProxmoxSSLError as exc:
|
||||
errors["base"] = "ssl_error"
|
||||
err = exc
|
||||
except ProxmoxInitFailed as exc:
|
||||
errors["base"] = "api_error_no_details"
|
||||
err = exc
|
||||
except ProxmoxNoNodesFound as exc:
|
||||
errors["base"] = "no_nodes_found"
|
||||
err = exc
|
||||
except ProxmoxNoVMLXCFound as exc:
|
||||
errors["base"] = "no_vmlxc_found"
|
||||
err = exc
|
||||
except ProxmoxConnectionError as exc:
|
||||
errors["base"] = "cannot_connect"
|
||||
err = exc
|
||||
@@ -370,6 +393,14 @@ class ProxmoxNoNodesFound(ProxmoxError):
|
||||
"""Error to indicate no nodes found."""
|
||||
|
||||
|
||||
class ProxmoxNoVMLXCFound(ProxmoxError):
|
||||
"""Error to indicate no LXC or VM found."""
|
||||
|
||||
|
||||
class ProxmoxInitFailed(ProxmoxError):
|
||||
"""Error to indicate API initialisation failure."""
|
||||
|
||||
|
||||
class ProxmoxConnectTimeout(ProxmoxError):
|
||||
"""Error to indicate a connection timeout."""
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
|
||||
},
|
||||
"error": {
|
||||
"api_error_no_details": "An error occurred while communicating with the Proxmox VE instance.",
|
||||
"cannot_connect": "Cannot connect to Proxmox VE server",
|
||||
"connect_timeout": "[%key:common::config_flow::error::timeout_connect%]",
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||
"no_nodes_found": "No active nodes found",
|
||||
"no_nodes_found": "No active nodes were found on the Proxmox VE server.",
|
||||
"no_vmlxc_found": "No LXC or VM were found on the Proxmox VE server.",
|
||||
"ssl_error": "SSL check failed. Check the SSL settings"
|
||||
},
|
||||
"step": {
|
||||
@@ -324,6 +326,9 @@
|
||||
"no_permission_vm_lxc_power": {
|
||||
"message": "The configured Proxmox VE user does not have permission to manage the power state of VMs and containers. Please grant the user the 'VM.PowerMgmt' permission and try again."
|
||||
},
|
||||
"no_vmlxc_found": {
|
||||
"message": "No LXC or VM were found on the Proxmox VE server."
|
||||
},
|
||||
"permissions_error": {
|
||||
"message": "Failed to retrieve Proxmox VE permissions. Please check your credentials and try again."
|
||||
},
|
||||
|
||||
@@ -85,8 +85,8 @@ def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
with patch(
|
||||
"homeassistant.components.proxmoxve.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
) as mock_setup:
|
||||
yield mock_setup
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -104,6 +104,9 @@ def mock_proxmox_client():
|
||||
mock_api.return_value = mock_instance
|
||||
mock_api_cf.return_value = mock_instance
|
||||
|
||||
mock_instance._mock_api = mock_api
|
||||
mock_instance._mock_api_cf = mock_api_cf
|
||||
|
||||
mock_instance.access.ticket.post.return_value = load_json_object_fixture(
|
||||
"access_ticket.json", DOMAIN
|
||||
)
|
||||
|
||||
@@ -147,8 +147,8 @@ async def test_form(
|
||||
"connect_timeout",
|
||||
),
|
||||
(
|
||||
ResourceException("404", "status_message", "content"),
|
||||
"no_nodes_found",
|
||||
ResourceException("500", "status_message", "content"),
|
||||
"api_error_no_details",
|
||||
),
|
||||
(
|
||||
requests.exceptions.ConnectionError("Connection error"),
|
||||
@@ -161,6 +161,71 @@ async def test_form_exceptions(
|
||||
mock_proxmox_client: MagicMock,
|
||||
exception: Exception,
|
||||
reason: str,
|
||||
) -> None:
|
||||
"""Test we handle all exceptions."""
|
||||
mock_proxmox_client._mock_api_cf.side_effect = exception
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=MOCK_USER_STEP,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user_auth"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=MOCK_USER_AUTH_STEP_PASSWORD,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": reason}
|
||||
|
||||
mock_proxmox_client._mock_api_cf.side_effect = None
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=MOCK_USER_AUTH_STEP_PASSWORD
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "reason"),
|
||||
[
|
||||
(
|
||||
AuthenticationError("Invalid credentials"),
|
||||
"invalid_auth",
|
||||
),
|
||||
(
|
||||
SSLError("SSL handshake failed"),
|
||||
"ssl_error",
|
||||
),
|
||||
(
|
||||
ConnectTimeout("Connection timed out"),
|
||||
"connect_timeout",
|
||||
),
|
||||
(
|
||||
ResourceException("400", "status_message", "content"),
|
||||
"no_nodes_found",
|
||||
),
|
||||
(
|
||||
requests.exceptions.ConnectionError("Connection error"),
|
||||
"cannot_connect",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_form_node_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_proxmox_client: MagicMock,
|
||||
exception: Exception,
|
||||
reason: str,
|
||||
) -> None:
|
||||
"""Test we handle all exceptions."""
|
||||
mock_proxmox_client.nodes.get.side_effect = exception
|
||||
@@ -201,7 +266,7 @@ async def test_form_exceptions(
|
||||
[
|
||||
(
|
||||
ResourceException("404", "status_message", "content"),
|
||||
"no_nodes_found",
|
||||
"no_vmlxc_found",
|
||||
),
|
||||
(
|
||||
requests.exceptions.ConnectionError("Connection error"),
|
||||
|
||||
Reference in New Issue
Block a user