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.
117 lines
4.7 KiB
Markdown
117 lines
4.7 KiB
Markdown
# napalm-vmware
|
|
|
|
NAPALM drivers for VMware vSphere, speaking the vSphere API through
|
|
[pyVmomi](https://github.com/vmware/pyvmomi):
|
|
|
|
| Driver | Endpoint | Device in netOrk |
|
|
|---|---|---|
|
|
| `vmware_esxi` | one ESXi host, addressed directly | the host: its vmnics, vmkernel NICs, sensors, VMs |
|
|
| `vmware_vcenter` | a vCenter Server | the vCenter: every VM it manages, with the ESXi host as the VM's `node` |
|
|
|
|
Both declare the `hypervisor` role from
|
|
[napalm-device-types](https://git.netork.io/NAPALM/napalm-device-types).
|
|
|
|
## Status
|
|
|
|
Tested against govmomi's **vcsim** simulator, in both ESXi and vCenter mode,
|
|
including real power and snapshot tasks. **Not yet tested against real
|
|
hardware**: see [Harvesting fixtures](#harvesting-fixtures).
|
|
|
|
| Method | ESXi | vCenter | Source |
|
|
|---|---|---|---|
|
|
| `get_facts` | ✅ | ✅ | host hardware + product / `about` |
|
|
| `get_interfaces`, `get_interfaces_ip` | ✅ | `{}` | vmnics + vmks |
|
|
| `get_lldp_neighbors` | ✅ | `{}` | `QueryNetworkHint` (LLDP, else CDP) |
|
|
| `get_environment` | ✅ | ✅ (per host) | quick stats + hardware sensors |
|
|
| `get_vms` | ✅ | ✅ | VMs, templates excluded |
|
|
| `get_vm_config` | ✅ | ✅ | virtual hardware |
|
|
| `start_vm`, `stop_vm`, `reboot_vm`, `suspend_vm` | ✅ | ✅ | power tasks / VMware Tools |
|
|
| `get_vm_snapshots`, `create/delete/rollback_vm_snapshot` | ✅ | ✅ | snapshot tree |
|
|
| `get_vm_storage_pools` | ✅ | ✅ | datastores |
|
|
| `get_virtual_networks` | ✅ | ✅ (+ dvPortgroups) | port groups |
|
|
| `get_device_warnings` | ✅ | ✅ | raw `{code, meta}` |
|
|
| VM provisioning, VIBs, updates, host reboot | — | — | out of scope for v1 |
|
|
|
|
Unverified assumptions, to be checked against real hardware:
|
|
|
|
- the HTTP fingerprints (`vmware esxi` on the Host Client page, `vcenter` on
|
|
the vSphere Client page)
|
|
- the free vSphere Hypervisor license reporting `editionKey` `esxBasic`
|
|
|
|
## Requirements
|
|
|
|
- HTTPS (443) to the host or vCenter. No SSH.
|
|
- An account that may read the inventory. For power and snapshot actions it
|
|
also needs *Virtual machine → Interaction → Power on/off/Reset/Suspend* and
|
|
*Virtual machine → Snapshot management*.
|
|
- **A paid license for any write.** On the free vSphere Hypervisor license
|
|
the API is read-only; the driver reports `vmware_api_read_only` and turns
|
|
the refusal into a readable error.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pip install -e vendor/napalm-device-types/ -e vendor/napalm-vmware/
|
|
```
|
|
|
|
## Usage
|
|
|
|
```python
|
|
from napalm_vmware import VmwareEsxiDriver
|
|
|
|
driver = VmwareEsxiDriver("esx01.example.lan", "root", "secret",
|
|
optional_args={"verify_ssl": False})
|
|
driver.open()
|
|
print(driver.get_facts())
|
|
for vm in driver.get_vms():
|
|
print(vm["name"], vm["status"], vm["vmid"])
|
|
driver.close()
|
|
```
|
|
|
|
`optional_args`: `port` (default 443), `verify_ssl` / `ssl_verify` (default
|
|
`True`; ESXi ships a self-signed certificate). Other keys are ignored.
|
|
|
|
VMs are addressed by name, by `vmid`, or by MoRef (`vm-42`). A name shared
|
|
by two VMs is refused rather than guessed.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
pytest # unit tests, no network
|
|
docker run -d --rm -p 127.0.0.1:8989:8989 vmware/vcsim -l 0.0.0.0:8989
|
|
docker run -d --rm -p 127.0.0.1:8990:8989 vmware/vcsim -esx -l 0.0.0.0:8989
|
|
VCSIM_VCENTER_PORT=8989 VCSIM_ESXI_PORT=8990 pytest -m vcsim
|
|
```
|
|
|
|
## Harvesting fixtures
|
|
|
|
```bash
|
|
tools/harvest.py esx01.example.lan root esxi8-dell # prompts for the password
|
|
tools/sanitize.py tools/harvest-out/esxi8-dell.json > tests/fixtures/esxi8-dell.json
|
|
```
|
|
|
|
`harvest.py` reads exactly the property paths in `napalm_vmware/paths.py`,
|
|
the ones the drivers read. `tools/harvest-out/` is gitignored. Read the
|
|
sanitised file before committing it.
|
|
|
|
## Design notes
|
|
|
|
**One seam.** Every read goes through `Inventory.collect(type, paths)`, a
|
|
PropertyCollector query with explicit paths, and every result is converted
|
|
by `to_plain()` into dicts, lists and scalars (managed objects become their
|
|
MoRef, data objects get a `_type`). The parsers in `napalm_vmware/parse/`
|
|
only ever see that plain form, so a harvested JSON file and a live host feed
|
|
them identically. Lazy attribute access on pyVmomi objects is avoided on
|
|
purpose: it fails on some servers where the individual paths work.
|
|
|
|
**`vmid` is the instance UUID** (`config.instanceUuid`). It survives vMotion
|
|
and re-registration and is unique within a vCenter; a MoRef is none of those.
|
|
The MoRef is reported alongside as `moref`.
|
|
|
|
**The vCenter device has no interfaces.** The hosts' NICs belong to the
|
|
hosts. Reporting them on the vCenter would attach their MACs to the wrong
|
|
device. Add a host with `vmware_esxi` to see its NICs.
|
|
|
|
**Warnings are raw.** `get_device_warnings()` returns `{code, meta}` only;
|
|
what a code means is decided in netOrk's `WARNING_CATALOG`.
|