"""Classify and read entries of a VM's ``config.hardware.device`` list.""" from __future__ import annotations import re from typing import Any _NIC_TYPES = frozenset( { "VirtualE1000", "VirtualE1000e", "VirtualPCNet32", "VirtualVmxnet", "VirtualVmxnet2", "VirtualVmxnet3", "VirtualVmxnet3Vrdma", "VirtualSriovEthernetCard", } ) _PASSTHROUGH_KIND = {"VirtualPCIPassthrough": "pci", "VirtualUSB": "usb"} _DATASTORE_IN_PATH = re.compile(r"^\[([^\]]+)\]") def devices(vm: dict[str, Any]) -> list[dict[str, Any]]: return vm.get("config.hardware.device") or [] def is_nic(device: dict[str, Any]) -> bool: return device.get("_type") in _NIC_TYPES def is_disk(device: dict[str, Any]) -> bool: return device.get("_type") == "VirtualDisk" def passthrough_kind(device: dict[str, Any]) -> str | None: return _PASSTHROUGH_KIND.get(device.get("_type", "")) def label(device: dict[str, Any]) -> str: """The name vSphere shows for a device (``"Hard disk 1"``), else its key.""" info = device.get("deviceInfo") or {} return info.get("label") or str(device.get("key", "")) def summary(device: dict[str, Any]) -> str: return (device.get("deviceInfo") or {}).get("summary", "") def nic_model(device: dict[str, Any]) -> str: """``"vmxnet3"``, ``"e1000e"`` ... -- the type name without ``Virtual``.""" return device.get("_type", "").removeprefix("Virtual").lower() def disk_bytes(device: dict[str, Any]) -> int: if device.get("capacityInBytes"): return int(device["capacityInBytes"]) return int(device.get("capacityInKB", 0)) * 1024 def disk_datastore(device: dict[str, Any]) -> str: """Datastore name from the backing file path ``"[datastore1] vm/vm.vmdk"``.""" path = (device.get("backing") or {}).get("fileName", "") match = _DATASTORE_IN_PATH.match(path) return match.group(1) if match else ""