Files
napalm-vmware/README.md
Christian Manivong b5c830acfe
CI / test (3.10) (push) Successful in 30s
CI / test (3.11) (push) Successful in 26s
CI / test (3.12) (push) Successful in 28s
CI / test (3.10) (pull_request) Successful in 27s
CI / test (3.11) (pull_request) Successful in 26s
CI / test (3.12) (pull_request) Successful in 27s
feat(vm-provision): declare the guest agent per guest OS, Linux only
Follows napalm-device-types 3.0, which replaces GUEST_AGENT_PACKAGES /
GUEST_AGENT_RUNCMD with GUEST_AGENTS = {guest_os: (packages, runcmd)}.
VMware lists Linux with open-vm-tools, as before, and refuses any other
guest_os before anything is created: BSD guests on VMware are optional
for now (NetOrk/netork#801).

The NoCloud network-config moved to napalm-device-types
(`provisioning.network_config`), which Proxmox now uses as well; the seed
module's copy is gone, and the tests check that the generic one is used.
2026-10-08 07:54:13 +02:00

153 lines
6.6 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}` |
| `reboot_host` | ✅ (maintenance mode only) | — | `RebootHost_Task` |
| `create_vm_from_cloud_init`, `destroy_vm`, `get_vm_status` | ✅ | ✅ | see [Provisioning](#provisioning) |
| `get_network_targets`, `get_image_storages` | ✅ | ✅ | port groups, datastores |
| VIBs, updates | — | — | not yet |
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*.
- For provisioning: `qemu-img` (package `qemu-utils`) where the driver runs,
and HTTPS from there to every ESXi host that may receive a VM -- through a
vCenter the disk upload goes straight to the host, not via the vCenter.
- **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), `image_cache_dir` (where
converted cloud images are kept; default a directory under the system temp
dir). 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.
## Provisioning
`create_vm_from_cloud_init` takes the same cloud images netOrk's catalog
offers for Proxmox (qcow2/raw):
1. The image is downloaded where the driver runs, its checksum verified (one
retry), and converted with `qemu-img` to a streamOptimized VMDK. The VMDK
is cached by URL in `image_cache_dir`; the download is not kept.
2. A host is chosen that is connected, not in maintenance mode, and sees the
datastore and every requested port group (the named datastore, or the one
with the most free space).
3. The VM is created from a minimal OVF descriptor (PVSCSI disk, VMXNET3
NICs) and the disk streamed in over NFC.
4. Requested MACs are pinned, the disk grown to `disk_resize_gb`, and a
NoCloud seed ISO (user-data, meta-data, network-config) uploaded next to
the VM's files and attached as a CD-ROM on a new SATA controller.
5. The VM is powered on. Any failure after step 3 removes the VM again.
A port group fixes its VLAN, so `get_network_targets` reports each one with
`kind="portgroup"`, `vlan_aware=False` and its `fixed_vlan_tag`; a NIC asking
for a different `vlan_tag` is refused. The guest agent netOrk installs is
`open-vm-tools` (`GUEST_AGENTS`), which reports the IP address back. Only
Linux guests are provisioned; `guest_os` other than `"linux"` is refused
(BSD guests on VMware: NetOrk/netork#801).
Unverified until #305: that each distribution's cloud kernel carries the
PVSCSI and VMXNET3 drivers.
## 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`.