Skip to content

vmware: resolve the VM tenant from resource pool, folder and cluster - #589

Merged
semx merged 1 commit into
developmentfrom
feature/vm-tenant-sources
Oct 10, 2026
Merged

semx merged 1 commit into
developmentfrom
feature/vm-tenant-sources

Conversation

@semx

@semx semx commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Tenant assignment for VMs from more than the VM name, as asked for in #531, #463 and #454, plus the resource pool filter from #494. All six options are off by default; without them nothing changes.

Options

option type default does
vm_tenant_resource_pool_relation regex = tenant list unset tenant from the VM's resource pool path (Parent/Child, root pool excluded) or its plain pool name
vm_tenant_folder_relation regex = tenant list unset tenant from the VM folder path relative to the datacenter's vm folder (Dept-A/Prod) or the plain folder name
vm_tenant_inherit_from_cluster bool False a VM that got no tenant from the relations above takes the cluster's tenant (cluster_tenant_relation, else the tenant on the NetBox cluster)
overwrite_vm_tenant bool True when False, a tenant already set on the NetBox VM is kept; a VM without one still gets the resolved tenant
vm_exclude_by_resource_pool_filter regex unset skip VMs whose pool path or plain pool name matches, like vm_exclude_filter
vm_include_by_resource_pool_filter regex unset keep only VMs whose pool path or plain pool name matches (one of the two is enough: the plain name of a VM in Customers/Gold is Gold, so ^Customers/ has to be satisfied by the path)

Order: vm_tenant_relation, resource pool, folder, cluster; the first match wins. IP addresses already take the VM's tenant through the device step of ip_tenant_inheritance_order, so the inheritance chain in #531 (cluster → VM → IP) works without further changes; a vcsim test pins it.

The root pool is recognised as the pool whose parent is the cluster, not by its name, so a child pool called Resources is not cut off. A VM in the root pool has an empty pool path and is judged by the plain name Resources only, by the filters and by the relations alike (same for a VM directly in the datacenter's VM folder, whose plain folder name is vm); otherwise ^Resources as an include filter would drop every root-pool VM, and .* as a relation would match an empty path. A VM without a resource pool (a template) passes the pool filters. Paths are walked up to 20 levels, far more than vCenter allows; if that limit is ever hit a warning says the path was cut off.

#463 also floated a tag-based variant (vm_tenant_folder_tag_relation); that is not in here, the direct mapping the reporter listed first and the pool mapping asked for later are.

Testing

  • 30 unit tests on the in-memory inventory (tests/test_vmware_vm_tenant_options.py): path helpers and their cache, the root pool found by its parent and not its name, the depth limit, precedence, empty paths, cluster inheritance from the relation and from the NetBox cluster object (dict, resolved object, unusable shapes), overwrite on and off with the existing tenant as object and as API dict, the filters including path-or-name for the include filter and exclude winning over include. 9 vcsim tests (tests/test_vmware_vm_tenant_vcsim.py) on the vc001 capture with its real folder names (they run against both captures, 42 test runs in all). On development without this change 38 of the 42 fail, 4 pass (those pin today's implicit behaviour).
  • Full suite: 322 passed, 6 skipped (development: 280).
  • With the options unset the handler produces the same inventory as development on vc001: 324 objects, byte-identical canonical dump.
  • Live NetBox 4.7.2 against vcsim with a nested pool Customers holding vm002 and folders Customers/Xyz, Customers/Abc: cluster_tenant_relation = .* = Cluster Tenant, pool relation Customers = Pool Tenant, folder relation Customers/Xyz = Xyz Tenant, Customers/Abc = Abc Tenant, inheritance on. Result: vm002 → Pool Tenant (pool wins over its folder), vm169 → Abc Tenant, the other 32 VMs → Cluster Tenant, the one VM IP → Cluster Tenant; second run writes nothing. overwrite_vm_tenant = False keeps a tenant set by hand and, when the resolved tenant equals the existing one, keeps the tenant referenced so its source tag does not flip. With vm002 moved into a nested pool Customers/Gold: the pool relation Customers = Pool Tenant still resolves it through the path, vm_include_by_resource_pool_filter = ^Customers/ keeps vm002 and skips the other 33 (did not match include filter in the log), vm_exclude_by_resource_pool_filter = ^Customers/ skips vm002 alone.

Reporters of the four issues: this is in the development image once merged; the call for testing has the details.

Adds vm_tenant_resource_pool_relation and vm_tenant_folder_relation,
which map a VM's resource pool path or folder path to a tenant the way
vm_tenant_relation maps its name; vm_tenant_inherit_from_cluster, which
gives a VM without a tenant of its own the tenant of its cluster; and
overwrite_vm_tenant, which when disabled keeps a tenant that was set by
hand in NetBox. The order is vm_tenant_relation, resource pool, folder,
cluster; the first match wins. IP addresses already take the VM's tenant
through the device step of ip_tenant_inheritance_order.

Also adds vm_exclude_by_resource_pool_filter and
vm_include_by_resource_pool_filter next to the name filters.

Resource pool and folder paths are built by walking the vCenter parent
chain up to the cluster root pool and the datacenter's vm folder, both
excluded, and are cached per managed object. The root pool is the pool
whose parent is the cluster, not the pool named "Resources", so a child
pool of that name is not mistaken for it.

Fixes #531
Fixes #463
Fixes #454
Fixes #494
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant