Two drivers from one package, both in the hypervisor role: - vmware_esxi talks to one host directly: facts, vmnics and vmkernel NICs, CDP/LLDP neighbours, sensors, VMs, datastores and port groups. - vmware_vcenter talks to a vCenter: every VM of every host it manages, with the host as the VM's node, plus distributed port groups. It reports no interfaces of its own; the hosts' NICs belong to the hosts. Both implement the HypervisorDriver VM contract: get_vms, get_vm_config, start/stop/reboot/suspend_vm and the four snapshot methods, and emit raw device warnings (maintenance mode, disconnected host, config issues, host managed by a vCenter, free license making the API read-only). Every read is a PropertyCollector query for the explicit paths in paths.py, converted by to_plain() into dicts and lists; the parsers only ever see that. tools/harvest.py dumps exactly those paths to JSON and tools/sanitize.py scrubs the dump, so a real host can become a test fixture without code changes. A VM's vmid is its instance UUID, which survives vMotion and re-registration; a MoRef does not. Tested against govmomi's vcsim in ESXi and vCenter mode, including real power and snapshot tasks. Not yet tested against real hardware.
81 lines
3.0 KiB
Python
81 lines
3.0 KiB
Python
"""get_interfaces / get_interfaces_ip for an ESXi host: vmnics and vmkernel NICs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from napalm_vmware.parse.interfaces import host_interfaces, host_interfaces_ip
|
|
|
|
|
|
class TestHostInterfaces:
|
|
def test_physical_nic_with_link(self, esxi_host):
|
|
vmnic0 = host_interfaces(esxi_host)["vmnic0"]
|
|
assert vmnic0 == {
|
|
"is_up": True,
|
|
"is_enabled": True,
|
|
"description": "nvmxnet3 0000:0b:00.0",
|
|
"last_flapped": -1.0,
|
|
"speed": 10000.0,
|
|
"mtu": 1500,
|
|
"mac_address": "00:0C:29:81:D8:A0",
|
|
}
|
|
|
|
def test_physical_nic_without_link_is_down(self, esxi_host):
|
|
esxi_host["config.network.pnic"][1].pop("linkSpeed", None)
|
|
vmnic1 = host_interfaces(esxi_host)["vmnic1"]
|
|
assert vmnic1["is_up"] is False
|
|
assert vmnic1["speed"] == 0.0
|
|
|
|
def test_mtu_comes_from_the_vswitch_the_nic_is_uplink_of(self, esxi_host):
|
|
esxi_host["config.network.vswitch"][0]["mtu"] = 9000
|
|
assert host_interfaces(esxi_host)["vmnic0"]["mtu"] == 9000
|
|
|
|
def test_nic_on_no_vswitch_has_default_mtu(self, esxi_host):
|
|
del esxi_host["config.network.vswitch"]
|
|
assert host_interfaces(esxi_host)["vmnic0"]["mtu"] == 1500
|
|
|
|
def test_vmkernel_nic(self, esxi_host):
|
|
assert host_interfaces(esxi_host)["vmk0"] == {
|
|
"is_up": True,
|
|
"is_enabled": True,
|
|
"description": "Management Network",
|
|
"last_flapped": -1.0,
|
|
"speed": 0.0,
|
|
"mtu": 1500,
|
|
"mac_address": "00:0C:29:81:D8:A0",
|
|
}
|
|
|
|
def test_host_without_network_config(self):
|
|
assert host_interfaces({"name": "h"}) == {}
|
|
|
|
|
|
class TestHostInterfacesIp:
|
|
def test_unassigned_address_is_left_out(self, esxi_host):
|
|
"""vcsim, like a DHCP vmk without a lease, reports 0.0.0.0."""
|
|
assert host_interfaces_ip(esxi_host) == {}
|
|
|
|
def test_ipv4_and_ipv6(self, esxi_host):
|
|
ip = esxi_host["config.network.vnic"][0]["spec"]["ip"]
|
|
ip["ipAddress"] = "192.0.2.10"
|
|
ip["subnetMask"] = "255.255.255.0"
|
|
ip["ipV6Config"] = {
|
|
"ipV6Address": [
|
|
{"ipAddress": "fe80::20c:29ff:fe81:d8a0", "prefixLength": 64},
|
|
{"ipAddress": "2001:db8::10", "prefixLength": 64},
|
|
]
|
|
}
|
|
assert host_interfaces_ip(esxi_host) == {
|
|
"vmk0": {
|
|
"ipv4": {"192.0.2.10": {"prefix_length": 24}},
|
|
"ipv6": {
|
|
"fe80::20c:29ff:fe81:d8a0": {"prefix_length": 64},
|
|
"2001:db8::10": {"prefix_length": 64},
|
|
},
|
|
}
|
|
}
|
|
|
|
def test_ipv6_only(self, esxi_host):
|
|
ip = esxi_host["config.network.vnic"][0]["spec"]["ip"]
|
|
ip["ipV6Config"] = {"ipV6Address": [{"ipAddress": "2001:db8::10", "prefixLength": 64}]}
|
|
assert host_interfaces_ip(esxi_host) == {
|
|
"vmk0": {"ipv6": {"2001:db8::10": {"prefix_length": 64}}}
|
|
}
|