"""NAPALM driver for a VMware ESXi host, addressed directly.""" from __future__ import annotations from typing import Any from napalm_device_types import FingerprintRule from pyVmomi import vim from napalm_vmware._plain import to_plain from napalm_vmware._tasks import invoke from napalm_vmware.actions import VmwareActionsMixin from napalm_vmware.base import VmwareBaseDriver from napalm_vmware.parse.facts import esxi_facts from napalm_vmware.parse.interfaces import host_interfaces, host_interfaces_ip from napalm_vmware.parse.lldp import lldp_neighbors class VmwareEsxiDriver(VmwareActionsMixin, VmwareBaseDriver): """One ESXi host. Its VMs, vmnics, vmkernel NICs, datastores and port groups.""" DRIVER_NAME = "vmware_esxi" API_TYPE = "HostAgent" STANDALONE = True # A host reboot runs through hardware POST before ESXi starts its services. REBOOT_SETTLE_SECONDS = 300 # Unverified against real hardware: the Host Client landing page says # "VMware ESXi"; a vCenter's does not, and it says "vCenter". HTTP_FINGERPRINT = [ FingerprintRule("vmware esxi", weight=9.0, mandatory=True), FingerprintRule("vcenter", weight=9.0, negative=True), ] def _host(self) -> dict[str, Any]: hosts = self._hosts() if not hosts: raise RuntimeError(f"{self.hostname} shows no host in its inventory") return hosts[0] def get_facts(self) -> dict[str, Any]: return esxi_facts(self._inventory.about(), self._host()) def get_interfaces(self) -> dict[str, dict[str, Any]]: return host_interfaces(self._host()) def get_interfaces_ip(self) -> dict[str, dict[str, Any]]: return host_interfaces_ip(self._host()) def get_lldp_neighbors(self) -> dict[str, list[dict[str, str]]]: network_system = self._host().get("configManager.networkSystem") if not network_system: return {} mo = self._mo(vim.host.NetworkSystem, network_system) try: hints = invoke(mo.QueryNetworkHint) except RuntimeError: return {} return lldp_neighbors(to_plain(hints) or [])