Skip to content

Commit

Permalink
Adds storage resources
Browse files Browse the repository at this point in the history
  • Loading branch information
dougiteixeira committed Nov 12, 2023
1 parent 2454ff4 commit 1f85e9b
Show file tree
Hide file tree
Showing 11 changed files with 562 additions and 273 deletions.
87 changes: 79 additions & 8 deletions custom_components/proxmoxve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
CONF_NODES,
CONF_QEMU,
CONF_REALM,
CONF_STORAGE,
CONF_VMS,
COORDINATORS,
DEFAULT_PORT,
Expand All @@ -59,6 +60,7 @@
ProxmoxLXCCoordinator,
ProxmoxNodeCoordinator,
ProxmoxQEMUCoordinator,
ProxmoxStorageCoordinator,
)

PLATFORMS = [
Expand Down Expand Up @@ -252,6 +254,25 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry):
remove_config_entry_id=config_entry.entry_id,
)


if config_entry.version == 3:
config_entry.version = 4
data_new = {
CONF_HOST: config_entry.data.get(CONF_HOST),
CONF_PORT: config_entry.data.get(CONF_PORT),
CONF_USERNAME: config_entry.data.get(CONF_USERNAME),
CONF_PASSWORD: config_entry.data.get(CONF_PASSWORD),
CONF_REALM: config_entry.data.get(CONF_REALM),
CONF_VERIFY_SSL: config_entry.data.get(CONF_VERIFY_SSL),
CONF_NODES: config_entry.data.get(CONF_NODES),
CONF_QEMU: config_entry.data.get(CONF_QEMU),
CONF_LXC: config_entry.data.get(CONF_LXC),
CONF_STORAGE: [],
}
hass.config_entries.async_update_entry(
config_entry, data=data_new, options={}
)

LOGGER.info("Migration to version %s successful", config_entry.version)

return True
Expand Down Expand Up @@ -383,7 +404,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
"platform": DOMAIN,
"host": config_entry.data[CONF_HOST],
"port": config_entry.data[CONF_PORT],
"resource_type": "QEMU",
"resource_type": ProxmoxType.QEMU,
"resource": vm_id,
},
)
Expand Down Expand Up @@ -419,11 +440,47 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
"platform": DOMAIN,
"host": config_entry.data[CONF_HOST],
"port": config_entry.data[CONF_PORT],
"resource_type": "LXC",
"resource_type": ProxmoxType.LXC,
"resource": container_id,
},
)

for storage_id in config_entry.data[CONF_STORAGE]:
if storage_id in [
(resource["storage"] if "storage" in resource else None)
for resource in resources
]:
async_delete_issue(
hass,
DOMAIN,
f"{config_entry.entry_id}_{storage_id}_resource_nonexistent",
)
coordinator_storage = ProxmoxStorageCoordinator(
hass=hass,
proxmox=proxmox,
api_category=ProxmoxType.Storage,
storage_id=storage_id,
)
await coordinator_storage.async_refresh()
coordinators[storage_id] = coordinator_storage
else:
async_create_issue(
hass,
DOMAIN,
f"{config_entry.entry_id}_{storage_id}_resource_nonexistent",
is_fixable=False,
severity=IssueSeverity.ERROR,
translation_key="resource_nonexistent",
translation_placeholders={
"integration": "Proxmox VE",
"platform": DOMAIN,
"host": config_entry.data[CONF_HOST],
"port": config_entry.data[CONF_PORT],
"resource_type": ProxmoxType.Storage,
"resource": storage_id,
},
)

hass.data[DOMAIN][config_entry.entry_id] = {
PROXMOX_CLIENT: proxmox_client,
COORDINATORS: coordinators,
Expand Down Expand Up @@ -476,7 +533,7 @@ def device_info(
config_entry: ConfigEntry,
api_category: ProxmoxType,
node: str | None = None,
vm_id: int | None = None,
resource_id: int | None = None,
create: bool | None = False,
):
"""Return the Device Info."""
Expand All @@ -488,27 +545,41 @@ def device_info(

proxmox_version = None
if api_category in (ProxmoxType.QEMU, ProxmoxType.LXC):
coordinator = coordinators[vm_id]
coordinator = coordinators[resource_id]
if (coordinator_data := coordinator.data) is not None:
vm_name = coordinator_data.name
node = coordinator_data.node

name = f"{api_category.upper()} {vm_name} ({vm_id})"
identifier = f"{config_entry.entry_id}_{api_category.upper()}_{vm_id}"
url = f"https://{host}:{port}/#v1:0:={api_category}/{vm_id}"
name = f"{api_category.upper()} {vm_name} ({resource_id})"
identifier = f"{config_entry.entry_id}_{api_category.upper()}_{resource_id}"
url = f"https://{host}:{port}/#v1:0:={api_category}/{resource_id}"
via_device = (
DOMAIN,
f"{config_entry.entry_id}_{ProxmoxType.Node.upper()}_{node}",
)
model = api_category.upper()

elif api_category is ProxmoxType.Storage:
coordinator = coordinators[resource_id]
if (coordinator_data := coordinator.data) is not None:
node = coordinator_data.node

name = f"{api_category.capitalize()} {resource_id}"
identifier = f"{config_entry.entry_id}_{api_category.upper()}_{resource_id}"
url = f"https://{host}:{port}/#v1:0:={api_category}/{node}/{resource_id}"
via_device = (
DOMAIN,
f"{config_entry.entry_id}_{ProxmoxType.Node.upper()}_{node}",
)
model = api_category.capitalize()

elif api_category is ProxmoxType.Node:
coordinator = coordinators[node]
if (coordinator_data := coordinator.data) is not None:
model_processor = coordinator_data.model
proxmox_version = f"Proxmox {coordinator_data.version}"

name = f"Node {node}"
name = f"{api_category.capitalize()} {node}"
identifier = f"{config_entry.entry_id}_{api_category.upper()}_{node}"
url = f"https://{host}:{port}/#v1:0:=node/{node}"
via_device = ("", "")
Expand Down
4 changes: 2 additions & 2 deletions custom_components/proxmoxve/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ async def async_setup_entry(
hass=hass,
config_entry=config_entry,
api_category=ProxmoxType.QEMU,
vm_id=vm_id,
resource_id=vm_id,
),
description=description,
resource_id=vm_id,
Expand All @@ -129,7 +129,7 @@ async def async_setup_entry(
hass=hass,
config_entry=config_entry,
api_category=ProxmoxType.LXC,
vm_id=container_id,
resource_id=container_id,
),
description=description,
resource_id=container_id,
Expand Down
4 changes: 2 additions & 2 deletions custom_components/proxmoxve/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ async def async_setup_entry(
hass=hass,
config_entry=config_entry,
api_category=ProxmoxType.QEMU,
vm_id=vm_id,
resource_id=vm_id,
),
description=description,
resource_id=vm_id,
Expand All @@ -209,7 +209,7 @@ async def async_setup_entry(
hass=hass,
config_entry=config_entry,
api_category=ProxmoxType.LXC,
vm_id=ct_id,
resource_id=ct_id,
),
description=description,
resource_id=ct_id,
Expand Down
72 changes: 68 additions & 4 deletions custom_components/proxmoxve/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
CONF_NODES,
CONF_QEMU,
CONF_REALM,
CONF_STORAGE,
CONF_VMS,
DEFAULT_PORT,
DEFAULT_REALM,
Expand Down Expand Up @@ -181,6 +182,11 @@ async def async_step_change_expose(
for lxc in self.config_entry.data[CONF_LXC]:
old_lxc.append(str(lxc))

old_storage = []

for storage in self.config_entry.data[CONF_STORAGE]:
old_storage.append(str(storage))

host = self.config_entry.data[CONF_HOST]
port = self.config_entry.data[CONF_PORT]
user = self.config_entry.data[CONF_USERNAME]
Expand Down Expand Up @@ -217,6 +223,7 @@ async def async_step_change_expose(
LOGGER.debug("Response API - Resources: %s", resources)
resource_qemu = {}
resource_lxc = {}
resource_storage = {}
for resource in resources:
if ("type" in resource) and (resource["type"] == ProxmoxType.Node):
if resource["node"] not in resource_nodes:
Expand All @@ -235,6 +242,13 @@ async def async_step_change_expose(
] = f"{resource['vmid']} {resource['name']}"
else:
resource_lxc[str(resource["vmid"])] = f"{resource['vmid']}"
if ("type" in resource) and (resource["type"] == ProxmoxType.Storage):
if "storage" in resource:
resource_storage[
str(resource["storage"])
] = f"{resource['storage']} {resource['id']}"
else:
resource_storage[str(resource["storage"])] = f"{resource['storage']}"

return self.async_show_form(
step_id="change_expose",
Expand All @@ -255,6 +269,12 @@ async def async_step_change_expose(
**resource_lxc,
}
),
vol.Optional(CONF_STORAGE, default=old_storage): cv.multi_select(
{
**dict.fromkeys(old_storage),
**resource_storage,
}
),
}
),
)
Expand Down Expand Up @@ -313,11 +333,11 @@ async def async_step_change_expose(

lxc_selecition = []
if (
CONF_QEMU in user_input
CONF_LXC in user_input
and (lxc_user := user_input.get(CONF_LXC)) is not None
):
for qemu in lxc_user:
lxc_selecition.append(qemu)
for lxc in lxc_user:
lxc_selecition.append(lxc)

for lxc_id in self.config_entry.data[CONF_LXC]:
if lxc_id not in lxc_selecition:
Expand All @@ -334,11 +354,37 @@ async def async_step_change_expose(
DOMAIN,
f"{self.config_entry.entry_id}_{lxc_id}_resource_nonexistent",
)

storage_selecition = []
if (
CONF_STORAGE in user_input
and (storage_user := user_input.get(CONF_STORAGE)) is not None
):
for storage in storage_user:
storage_selecition.append(storage)

for storage_id in self.config_entry.data[CONF_STORAGE]:
if storage_id not in storage_selecition:
# Remove device
identifier = (
f"{self.config_entry.entry_id}_{ProxmoxType.Storage.upper()}_{storage_id}"
)
await self.async_remove_device(
entry_id=self.config_entry.entry_id,
device_identifier=identifier,
)
async_delete_issue(
self.hass,
DOMAIN,
f"{self.config_entry.entry_id}_{storage_id}_resource_nonexistent",
)

config_data.update(
{
CONF_NODES: node_selecition,
CONF_QEMU: qemu_selecition,
CONF_LXC: lxc_selecition,
CONF_STORAGE: storage_selecition,
}
)

Expand Down Expand Up @@ -372,7 +418,7 @@ async def async_remove_device(
class ProxmoxVEConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""ProxmoxVE Config Flow class."""

VERSION = 3
VERSION = 4
_reauth_entry: config_entries.ConfigEntry | None = None

def __init__(self) -> None:
Expand Down Expand Up @@ -722,6 +768,7 @@ async def async_step_expose(
resource_nodes = []
resource_qemu = {}
resource_lxc = {}
resource_storage = {}
if resources is None:
return self.async_abort(reason="no_resources")
for resource in resources:
Expand All @@ -742,6 +789,13 @@ async def async_step_expose(
] = f"{resource['vmid']} {resource['name']}"
else:
resource_lxc[str(resource["vmid"])] = f"{resource['vmid']}"
if ("type" in resource) and (resource["type"] == ProxmoxType.Storage):
if "storage" in resource:
resource_storage[
str(resource["storage"])
] = f"{resource['storage']} {resource['id']}"
else:
resource_lxc[str(resource["storage"])] = f"{resource['storage']}"

return self.async_show_form(
step_id="expose",
Expand All @@ -750,6 +804,7 @@ async def async_step_expose(
vol.Required(CONF_NODES): cv.multi_select(resource_nodes),
vol.Optional(CONF_QEMU): cv.multi_select(resource_qemu),
vol.Optional(CONF_LXC): cv.multi_select(resource_lxc),
vol.Optional(CONF_STORAGE): cv.multi_select(resource_storage),
}
),
)
Expand Down Expand Up @@ -781,6 +836,15 @@ async def async_step_expose(
for lxc_selection in lxc_user:
self._config[CONF_LXC].append(lxc_selection)

if CONF_STORAGE not in self._config:
self._config[CONF_STORAGE] = []
if (
CONF_STORAGE in user_input
and (storage_user := user_input.get(CONF_STORAGE)) is not None
):
for storage_selection in storage_user:
self._config[CONF_STORAGE].append(storage_selection)

return self.async_create_entry(
title=(f"{self._config[CONF_HOST]}:{self._config[CONF_PORT]}"),
data=self._config,
Expand Down
2 changes: 2 additions & 0 deletions custom_components/proxmoxve/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
CONF_QEMU = "qemu"
CONF_REALM = "realm"
CONF_VMS = "vms"
CONF_STORAGE="storage"

PROXMOX_CLIENT = "proxmox_client"

Expand All @@ -41,6 +42,7 @@ class ProxmoxType(StrEnum):
Node = "node"
QEMU = "qemu"
LXC = "lxc"
Storage = "storage"


class ProxmoxCommand(StrEnum):
Expand Down
Loading

0 comments on commit 1f85e9b

Please sign in to comment.