Files
pulse/internal/vmware/fixtures.go
T
rcourtman eac9ffcabf feat(vmware): ingest real vCenter tags instead of provenance placeholders
The vSphere adapter filled `Resource.Tags` with six fixed strings on every
resource — `vmware`, `vsphere`, `<kind>`, `source:vcenter`,
`connection:<name>`, `power:<state>` — and never read vCenter's own tag and
category system. Every VM in an estate returned a byte-identical set, so the
workload Tags column rendered the same dots on every row and filtering on any
of them selected everything. Commit 6b78feba8 default-hid the column and said
in as many words that the hide was a stopgap awaiting this fix.

`internal/vmware/client_tags.go` reads the CIS tagging service. That is a
different endpoint family from the `/api/vcenter/...` inventory reads, but the
same vSphere Automation API, so it reuses the caller's `/api/session` token
rather than opening and managing a second session. Associations come from one
batched `list-attached-tags-on-objects` POST per bounded object batch, never a
per-object request; tag and category names resolve through a client-scoped
catalog with a 10-minute TTL, so a steady-state refresh of a tagged estate
costs only the association reads while a rename still converges without a
restart. A vCenter without the tagging service, or an account without the tag
read privilege, degrades into a `tags` stage enrichment issue and leaves the
inventory untagged; it never fails the refresh.

The provenance strings stay. `Resource.Tags` is the only keyword set
`resourceSearchMatch.ts`, the `?tags=` resources filter, and saved
report-schedule tag filters read — `collectSearchCandidates` gathers no
`technology`, `type`, or `platformScopes` candidate — so dropping "vmware" or
"vsphere" would silently stop matching searches and saved filters that depend
on them. Real vCenter labels are appended to that set, never substituted for
it.

Because that flat set is deliberately mixed, it is the wrong source for a
per-row Tags cell. Real tags therefore also land on a canonical `VMware.Tags`
facet that carries vCenter's category alongside each name, and
`useWorkloads.ts` maps `WorkloadGuest.tags` from that facet for any resource
carrying VMware metadata — including the empty case, so a vSphere VM nobody
tagged renders an empty cell instead of falling back to the provenance dots.
vCenter tag names are unique only inside their category, so the flat label is
`category:name`: two categories may each hold a "Production".

With the column carrying per-row meaning again, `tags` leaves
VMWARE_WORKLOAD_DEFAULT_HIDDEN_COLUMN_IDS and the `defaultHiddenMigrationIds`
retirement list, and the state-model test that pinned the stopgap now pins its
absence. No un-hide migration ships alongside it: 6b78feba8 is on main but no tag
contains it, so the stopgap never shipped and no install carries the
auto-hidden preference. That holds only while the two stay together — the
migration writes the hide into each user's saved preference on first load,
so an rc cut from main carrying the stopgap without this commit would make
an explicit un-hide path necessary.

Mock fixtures carry uneven tag coverage — several categories on some objects,
one on others, none on the rest — because a uniform fixture set would hide
exactly the defect this data exists to catch.

Verified against a mock estate built from this branch: `/api/resources`
returns provenance plus real labels on the flat set and only real labels on
`vmware.tags`; the Tags column renders 2-4 dots per tagged VM and none for
untagged ones; a dot's tooltip reads `Backup:Nightly`, and clicking it
searches `tags:Backup:Nightly` and narrows 18 VMs to the 3 that carry it.

Contract deltas: performance-and-scalability.md Extension Point 17 replaces
the stopgap paragraph with the two-surface tag contract and the bounded
tag-read budget; unified-resources.md states the keyword-union vs facet split
and that a present-but-empty facet means "no operator tags" rather than a
fallback; storage-recovery.md extends its VMware descriptive-only boundary to
`vmware.tags`, because vCenter tag vocabularies read like protection policy
(`Backup:Nightly`) and a label the operator wrote must never satisfy a
coverage or compliance verdict that recovery-owned evidence should decide.
2026-08-06 20:50:46 +01:00

1168 lines
45 KiB
Go

package vmware
import (
"fmt"
"strings"
"time"
)
func DefaultFixtures() InventorySnapshot {
collectedAt := time.Date(2026, time.March, 31, 9, 45, 0, 0, time.UTC)
accessible := true
multipleHostAccess := true
snapshot := defaultFixturesPrimaryCluster(collectedAt, accessible, multipleHostAccess)
appendEdgeClusterFixtures(&snapshot, collectedAt, accessible, multipleHostAccess)
applyInventoryClusterServices(&snapshot)
applyFixtureTags(&snapshot)
return snapshot
}
// applyFixtureTags attaches the mock estate's vCenter tags. Real estates are
// tagged unevenly — some objects carry several categories, some carry one, and
// some were never tagged at all — so the fixture keeps that shape rather than
// giving every object an identical set. A uniform set would hide exactly the
// bug this data is meant to exercise: a Tags column that repeats itself on
// every row.
func applyFixtureTags(snapshot *InventorySnapshot) {
if snapshot == nil {
return
}
tag := func(category, name string) InventoryTag {
return InventoryTag{
TagID: fmt.Sprintf("urn:vmomi:InventoryServiceTag:mock-%s-%s:GLOBAL", strings.ToLower(category), strings.ToLower(name)),
Name: name,
CategoryID: fmt.Sprintf("urn:vmomi:InventoryServiceCategory:mock-%s:GLOBAL", strings.ToLower(category)),
Category: category,
}
}
hostTags := map[string][]InventoryTag{
"host-101": {tag("Environment", "Production"), tag("Rack", "R1")},
"host-102": {tag("Environment", "Production"), tag("Rack", "R1")},
"host-103": {tag("Environment", "Production"), tag("Rack", "R2")},
"host-104": {tag("Environment", "Staging"), tag("Rack", "R2")},
"host-201": {tag("Environment", "Production"), tag("Site", "Edge")},
"host-202": {tag("Environment", "Production"), tag("Site", "Edge")},
}
vmTags := map[string][]InventoryTag{
"vm-201": {tag("Environment", "Production"), tag("Owner", "Platform"), tag("Backup", "Nightly")},
"vm-202": {tag("Environment", "Production"), tag("Owner", "Data"), tag("Backup", "Nightly"), tag("Compliance", "PCI")},
"vm-203": {tag("Environment", "Production"), tag("Owner", "AppDev")},
"vm-204": {tag("Environment", "Staging"), tag("Owner", "AppDev")},
"vm-205": {tag("Environment", "Production"), tag("Owner", "Platform"), tag("Backup", "Weekly")},
"vm-301": {tag("Environment", "Production"), tag("Owner", "AppDev"), tag("Site", "Edge")},
"vm-302": {tag("Environment", "Production"), tag("Owner", "AppDev"), tag("Site", "Edge")},
"vm-303": {tag("Environment", "Production"), tag("Owner", "Data"), tag("Backup", "Nightly")},
"vm-304": {tag("Owner", "Platform"), tag("Backup", "None")},
"vm-305": {tag("Owner", "Platform"), tag("Backup", "None")},
"vm-306": {tag("Environment", "Production"), tag("Owner", "Platform")},
"vm-308": {tag("Environment", "Production"), tag("Owner", "Desktop"), tag("Compliance", "PCI")},
"vm-309": {tag("Environment", "Production"), tag("Owner", "Desktop")},
"vm-310": {tag("Owner", "Platform"), tag("Site", "Edge")},
"vm-311": {tag("Owner", "Platform"), tag("Site", "Edge")},
}
for i := range snapshot.Hosts {
if tags, ok := hostTags[snapshot.Hosts[i].Host]; ok {
sortInventoryTags(tags)
snapshot.Hosts[i].Tags = tags
}
}
for i := range snapshot.VMs {
if tags, ok := vmTags[snapshot.VMs[i].VM]; ok {
sortInventoryTags(tags)
snapshot.VMs[i].Tags = tags
}
}
}
func defaultFixturesPrimaryCluster(
collectedAt time.Time,
accessible bool,
multipleHostAccess bool,
) InventorySnapshot {
primaryHA := true
primaryDRS := true
return InventorySnapshot{
ConnectionID: "vc-mock-1",
ConnectionName: "Lab vCenter",
VCenterHost: "vcsa.lab.local",
VIRelease: "8.0.3",
CollectedAt: collectedAt,
Clusters: []InventoryCluster{{
Cluster: "domain-c101",
Name: "Production Cluster",
HAEnabled: &primaryHA,
DRSEnabled: &primaryDRS,
}},
Hosts: []InventoryHost{
{
Host: "host-101",
Name: "esxi-01.lab.local",
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: "uuid-host-101",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-h4",
FolderName: "Cluster Hosts",
DatastoreIDs: []string{"datastore-201", "datastore-202", "datastore-203"},
DatastoreNames: []string{"nvme-primary", "archive-tier", "analytics-vsan"},
OverallStatus: "green",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(24.6),
MemoryPercent: float64Ptr(56.3),
MemoryUsedBytes: int64Ptr(48_370_278_400),
MemoryTotalBytes: int64Ptr(85_899_345_920),
NetInBytesPerSecond: float64Ptr(1_340_000),
NetOutBytesPerSecond: float64Ptr(1_040_000),
DiskReadBytesPerSecond: float64Ptr(2_480_000),
DiskWriteBytesPerSecond: float64Ptr(2_040_000),
},
RecentTasks: []InventoryTask{{
Task: "task-301",
Name: "Apply host profile remediation",
State: "success",
StartedAt: collectedAt.Add(-28 * time.Minute),
}},
RecentEvents: []InventoryEvent{{
Event: "event-601",
Type: "HostConnectedEvent",
Message: "Host reconnected to vCenter and is reporting healthy telemetry",
User: "svc-pulse",
CreatedAt: collectedAt.Add(-52 * time.Minute),
}},
},
{
Host: "host-102",
Name: "esxi-02.lab.local",
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: "uuid-host-102",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-h4",
FolderName: "Cluster Hosts",
DatastoreIDs: []string{"datastore-201", "datastore-204"},
DatastoreNames: []string{"nvme-primary", "backup-nfs"},
OverallStatus: "yellow",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(43.6),
MemoryPercent: float64Ptr(71.5),
MemoryUsedBytes: int64Ptr(61_419_929_600),
MemoryTotalBytes: int64Ptr(85_899_345_920),
NetInBytesPerSecond: float64Ptr(1_960_000),
NetOutBytesPerSecond: float64Ptr(1_420_000),
DiskReadBytesPerSecond: float64Ptr(3_180_000),
DiskWriteBytesPerSecond: float64Ptr(2_540_000),
},
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-401",
Name: "Host memory contention",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-11 * time.Minute),
}},
RecentTasks: []InventoryTask{{
Task: "task-302",
Name: "vMotion virtual machine",
State: "running",
StartedAt: collectedAt.Add(-3 * time.Minute),
}},
},
{
Host: "host-103",
Name: "esxi-03.lab.local",
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: "uuid-host-103",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-h4",
FolderName: "Cluster Hosts",
DatastoreIDs: []string{"datastore-201", "datastore-203"},
DatastoreNames: []string{"nvme-primary", "analytics-vsan"},
OverallStatus: "green",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(18.9),
MemoryPercent: float64Ptr(49.2),
MemoryUsedBytes: int64Ptr(42_271_203_328),
MemoryTotalBytes: int64Ptr(85_899_345_920),
NetInBytesPerSecond: float64Ptr(980_000),
NetOutBytesPerSecond: float64Ptr(910_000),
DiskReadBytesPerSecond: float64Ptr(1_860_000),
DiskWriteBytesPerSecond: float64Ptr(1_220_000),
},
RecentTasks: []InventoryTask{{
Task: "task-303",
Name: "Enter maintenance mode check",
State: "success",
StartedAt: collectedAt.Add(-43 * time.Minute),
}},
},
{
Host: "host-104",
Name: "esxi-04.lab.local",
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: "uuid-host-104",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-h4",
FolderName: "Cluster Hosts",
DatastoreIDs: []string{"datastore-202", "datastore-203", "datastore-204"},
DatastoreNames: []string{"archive-tier", "analytics-vsan", "backup-nfs"},
OverallStatus: "green",
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(31.4),
MemoryPercent: float64Ptr(63.7),
MemoryUsedBytes: int64Ptr(54_722_805_760),
MemoryTotalBytes: int64Ptr(85_899_345_920),
NetInBytesPerSecond: float64Ptr(1_420_000),
NetOutBytesPerSecond: float64Ptr(1_260_000),
DiskReadBytesPerSecond: float64Ptr(2_660_000),
DiskWriteBytesPerSecond: float64Ptr(2_180_000),
},
RecentEvents: []InventoryEvent{{
Event: "event-602",
Type: "HostProfileAppliedEvent",
Message: "Host profile compliance restored after storage heartbeat remediation",
User: "svc-pulse",
CreatedAt: collectedAt.Add(-67 * time.Minute),
}},
},
},
VMs: []InventoryVM{
{
VM: "vm-201",
Name: "orders-api-01",
PowerState: "POWERED_ON",
CPUCount: 4,
MemorySizeMiB: 16 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v7",
FolderName: "Production VMs",
ResourcePoolID: "resgroup-22",
ResourcePoolName: "Tier 1",
RuntimeHostID: "host-101",
RuntimeHostName: "esxi-01.lab.local",
DatastoreIDs: []string{"datastore-201"},
DatastoreNames: []string{"nvme-primary"},
InstanceUUID: "vm-instance-201",
BIOSUUID: "vm-bios-201",
GuestOSFamily: "LINUX",
GuestHostname: "orders-api-01.internal",
GuestIPAddresses: []string{"10.42.10.21"},
OverallStatus: "green",
SnapshotCount: 1,
CurrentSnapshotID: "snapshot-201",
NetworkAdapters: fixtureVMNetworkAdapters("vm-201", "VM Network", true),
VirtualDisks: fixtureVMVirtualDisks("vm-201", "nvme-primary", 128_000_000_000),
Tools: fixtureVMTools("POWERED_ON", "green"),
Hardware: fixtureVMHardware("UBUNTU_64", "VMX_20", true),
SnapshotTree: []InventoryVMSnapshot{{
Snapshot: "snapshot-201",
Name: "pre-deploy-checkpoint",
Description: "Before service deployment",
ID: 201,
CreatedAt: inventorySnapshotTime(collectedAt.Add(-46 * time.Minute)),
State: "poweredOn",
Quiesced: true,
Current: true,
}},
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(36.2),
MemoryPercent: float64Ptr(64.4),
MemoryUsedBytes: int64Ptr(11_058_069_504),
MemoryTotalBytes: int64Ptr(17_179_869_184),
NetInBytesPerSecond: float64Ptr(620_000),
NetOutBytesPerSecond: float64Ptr(710_000),
DiskReadBytesPerSecond: float64Ptr(1_180_000),
DiskWriteBytesPerSecond: float64Ptr(940_000),
},
RecentEvents: []InventoryEvent{{
Event: "event-501",
Type: "VmMessageEvent",
Message: "Snapshot completed successfully",
User: "svc-pulse",
CreatedAt: collectedAt.Add(-46 * time.Minute),
}},
},
{
VM: "vm-202",
Name: "postgres-ha-01",
PowerState: "POWERED_ON",
CPUCount: 8,
MemorySizeMiB: 32 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v7",
FolderName: "Production VMs",
ResourcePoolID: "resgroup-23",
ResourcePoolName: "Stateful",
RuntimeHostID: "host-102",
RuntimeHostName: "esxi-02.lab.local",
DatastoreIDs: []string{"datastore-201", "datastore-202"},
DatastoreNames: []string{"nvme-primary", "archive-tier"},
InstanceUUID: "vm-instance-202",
BIOSUUID: "vm-bios-202",
GuestOSFamily: "LINUX",
GuestHostname: "postgres-ha-01.internal",
GuestIPAddresses: []string{"10.42.10.32"},
OverallStatus: "yellow",
SnapshotCount: 3,
CurrentSnapshotID: "snapshot-213",
NetworkAdapters: fixtureVMNetworkAdapters("vm-202", "Database Network", true),
VirtualDisks: fixtureVMVirtualDisks("vm-202", "nvme-primary", 256_000_000_000),
Tools: fixtureVMTools("POWERED_ON", "yellow"),
Hardware: fixtureVMHardware("RHEL_8_64", "VMX_19", true),
SnapshotTree: []InventoryVMSnapshot{{
Snapshot: "snapshot-211",
Name: "baseline",
ID: 211,
CreatedAt: inventorySnapshotTime(collectedAt.Add(-72 * time.Hour)),
State: "poweredOn",
Quiesced: true,
Children: []InventoryVMSnapshot{{
Snapshot: "snapshot-212",
Name: "schema-migration",
ID: 212,
CreatedAt: inventorySnapshotTime(collectedAt.Add(-36 * time.Hour)),
State: "poweredOn",
Quiesced: true,
Children: []InventoryVMSnapshot{{
Snapshot: "snapshot-213",
Name: "post-migration",
ID: 213,
CreatedAt: inventorySnapshotTime(collectedAt.Add(-18 * time.Hour)),
State: "poweredOn",
Current: true,
}},
}},
}},
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(58.8),
MemoryPercent: float64Ptr(82.1),
MemoryUsedBytes: int64Ptr(28_215_830_528),
MemoryTotalBytes: int64Ptr(34_359_738_368),
NetInBytesPerSecond: float64Ptr(880_000),
NetOutBytesPerSecond: float64Ptr(930_000),
DiskReadBytesPerSecond: float64Ptr(2_940_000),
DiskWriteBytesPerSecond: float64Ptr(3_220_000),
},
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-402",
Name: "Virtual machine memory usage",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-17 * time.Minute),
}},
RecentTasks: []InventoryTask{{
Task: "task-304",
Name: "Consolidate virtual machine disks",
State: "queued",
StartedAt: collectedAt.Add(-2 * time.Minute),
}},
},
{
VM: "vm-203",
Name: "web-frontend-01",
PowerState: "POWERED_ON",
CPUCount: 4,
MemorySizeMiB: 12 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v7",
FolderName: "Production VMs",
ResourcePoolID: "resgroup-22",
ResourcePoolName: "Tier 1",
RuntimeHostID: "host-103",
RuntimeHostName: "esxi-03.lab.local",
DatastoreIDs: []string{"datastore-203"},
DatastoreNames: []string{"analytics-vsan"},
InstanceUUID: "vm-instance-203",
BIOSUUID: "vm-bios-203",
GuestOSFamily: "LINUX",
GuestHostname: "web-frontend-01.internal",
GuestIPAddresses: []string{"10.42.10.44"},
OverallStatus: "green",
SnapshotCount: 1,
NetworkAdapters: fixtureVMNetworkAdapters("vm-203", "Web Network", true),
VirtualDisks: fixtureVMVirtualDisks("vm-203", "analytics-vsan", 96_000_000_000),
Tools: fixtureVMTools("POWERED_ON", "green"),
Hardware: fixtureVMHardware("UBUNTU_64", "VMX_20", true),
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(22.1),
MemoryPercent: float64Ptr(51.2),
MemoryUsedBytes: int64Ptr(6_589_939_712),
MemoryTotalBytes: int64Ptr(12_884_901_888),
NetInBytesPerSecond: float64Ptr(510_000),
NetOutBytesPerSecond: float64Ptr(690_000),
DiskReadBytesPerSecond: float64Ptr(880_000),
DiskWriteBytesPerSecond: float64Ptr(620_000),
},
},
{
VM: "vm-204",
Name: "observability-01",
PowerState: "POWERED_ON",
CPUCount: 8,
MemorySizeMiB: 24 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v9",
FolderName: "Platform VMs",
ResourcePoolID: "resgroup-25",
ResourcePoolName: "Platform",
RuntimeHostID: "host-104",
RuntimeHostName: "esxi-04.lab.local",
DatastoreIDs: []string{"datastore-203", "datastore-204"},
DatastoreNames: []string{"analytics-vsan", "backup-nfs"},
InstanceUUID: "vm-instance-204",
BIOSUUID: "vm-bios-204",
GuestOSFamily: "LINUX",
GuestHostname: "observability-01.internal",
GuestIPAddresses: []string{"10.42.20.15"},
OverallStatus: "green",
SnapshotCount: 2,
NetworkAdapters: fixtureVMNetworkAdapters("vm-204", "Platform Network", true),
VirtualDisks: fixtureVMVirtualDisks("vm-204", "analytics-vsan", 192_000_000_000),
Tools: fixtureVMTools("POWERED_ON", "green"),
Hardware: fixtureVMHardware("UBUNTU_64", "VMX_20", true),
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(27.8),
MemoryPercent: float64Ptr(59.6),
MemoryUsedBytes: int64Ptr(15_367_036_928),
MemoryTotalBytes: int64Ptr(25_769_803_776),
NetInBytesPerSecond: float64Ptr(740_000),
NetOutBytesPerSecond: float64Ptr(680_000),
DiskReadBytesPerSecond: float64Ptr(1_160_000),
DiskWriteBytesPerSecond: float64Ptr(1_020_000),
},
},
{
VM: "vm-205",
Name: "windows-jump-01",
PowerState: "POWERED_ON",
CPUCount: 4,
MemorySizeMiB: 8 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v10",
FolderName: "Utility VMs",
ResourcePoolID: "resgroup-26",
ResourcePoolName: "Utility",
RuntimeHostID: "host-103",
RuntimeHostName: "esxi-03.lab.local",
DatastoreIDs: []string{"datastore-203"},
DatastoreNames: []string{"analytics-vsan"},
InstanceUUID: "vm-instance-205",
BIOSUUID: "vm-bios-205",
GuestOSFamily: "WINDOWS",
GuestHostname: "windows-jump-01.internal",
GuestIPAddresses: []string{"10.42.30.18"},
OverallStatus: "green",
SnapshotCount: 0,
NetworkAdapters: fixtureVMNetworkAdapters("vm-205", "Utility Network", true),
VirtualDisks: fixtureVMVirtualDisks("vm-205", "analytics-vsan", 80_000_000_000),
Tools: fixtureVMTools("POWERED_ON", "green"),
Hardware: fixtureVMHardware("WINDOWS_2019_64", "VMX_19", true),
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(16.8),
MemoryPercent: float64Ptr(46.1),
MemoryUsedBytes: int64Ptr(3_959_726_080),
MemoryTotalBytes: int64Ptr(8_589_934_592),
NetInBytesPerSecond: float64Ptr(180_000),
NetOutBytesPerSecond: float64Ptr(220_000),
DiskReadBytesPerSecond: float64Ptr(320_000),
DiskWriteBytesPerSecond: float64Ptr(280_000),
},
},
{
VM: "vm-206",
Name: "batch-worker-01",
PowerState: "POWERED_OFF",
CPUCount: 4,
MemorySizeMiB: 8 * 1024,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
ComputeResourceID: "domain-c101",
ComputeResourceName: "Production Cluster",
ClusterID: "domain-c101",
ClusterName: "Production Cluster",
FolderID: "group-v8",
FolderName: "Batch VMs",
ResourcePoolID: "resgroup-24",
ResourcePoolName: "Workers",
RuntimeHostID: "host-101",
RuntimeHostName: "esxi-01.lab.local",
DatastoreIDs: []string{"datastore-202"},
DatastoreNames: []string{"archive-tier"},
InstanceUUID: "vm-instance-206",
BIOSUUID: "vm-bios-206",
GuestOSFamily: "LINUX",
GuestHostname: "batch-worker-01.internal",
GuestIPAddresses: []string{},
OverallStatus: "gray",
VirtualDisks: fixtureVMVirtualDisks("vm-206", "archive-tier", 64_000_000_000),
Tools: fixtureVMTools("POWERED_OFF", "gray"),
Hardware: fixtureVMHardware("OTHER_64", "VMX_17", false),
},
},
Datastores: []InventoryDatastore{
{
Datastore: "datastore-201",
Name: "nvme-primary",
Type: "VMFS",
FreeSpace: 4_600_000_000_000,
Capacity: 8_000_000_000_000,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-s4",
FolderName: "Datastores",
HostIDs: []string{"host-101", "host-102", "host-103"},
HostNames: []string{"esxi-01.lab.local", "esxi-02.lab.local", "esxi-03.lab.local"},
VMIDs: []string{"vm-201", "vm-202"},
VMNames: []string{"orders-api-01", "postgres-ha-01"},
Accessible: &accessible,
MultipleHostAccess: &multipleHostAccess,
MaintenanceMode: "normal",
URL: "ds:///vmfs/volumes/datastore-201/",
OverallStatus: "green",
},
{
Datastore: "datastore-202",
Name: "archive-tier",
Type: "NFS41",
FreeSpace: 12_400_000_000_000,
Capacity: 16_000_000_000_000,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-s4",
FolderName: "Datastores",
HostIDs: []string{"host-101", "host-104"},
HostNames: []string{"esxi-01.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-202", "vm-206"},
VMNames: []string{"postgres-ha-01", "batch-worker-01"},
Accessible: &accessible,
MultipleHostAccess: &multipleHostAccess,
MaintenanceMode: "normal",
URL: "ds:///nfs/archive-tier/",
OverallStatus: "yellow",
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-403",
Name: "Datastore latency above threshold",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-9 * time.Minute),
}},
RecentTasks: []InventoryTask{{
Task: "task-305",
Name: "Rescan datastore",
State: "success",
StartedAt: collectedAt.Add(-14 * time.Minute),
}},
},
{
Datastore: "datastore-203",
Name: "analytics-vsan",
Type: "vSAN",
FreeSpace: 6_900_000_000_000,
Capacity: 12_000_000_000_000,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-s4",
FolderName: "Datastores",
HostIDs: []string{"host-101", "host-103", "host-104"},
HostNames: []string{"esxi-01.lab.local", "esxi-03.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-203", "vm-204", "vm-205"},
VMNames: []string{"web-frontend-01", "observability-01", "windows-jump-01"},
Accessible: &accessible,
MultipleHostAccess: &multipleHostAccess,
MaintenanceMode: "normal",
URL: "ds:///vsan/analytics-vsan/",
OverallStatus: "green",
},
{
Datastore: "datastore-204",
Name: "backup-nfs",
Type: "NFS41",
FreeSpace: 20_800_000_000_000,
Capacity: 24_000_000_000_000,
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-s4",
FolderName: "Datastores",
HostIDs: []string{"host-102", "host-104"},
HostNames: []string{"esxi-02.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-204"},
VMNames: []string{"observability-01"},
Accessible: &accessible,
MultipleHostAccess: &multipleHostAccess,
MaintenanceMode: "normal",
URL: "ds:///nfs/backup-nfs/",
OverallStatus: "green",
RecentTasks: []InventoryTask{{
Task: "task-306",
Name: "Backup consistency check",
State: "success",
StartedAt: collectedAt.Add(-74 * time.Minute),
}},
},
},
Networks: []InventoryNetwork{
{
Network: "network-101",
Name: "VM Network",
Type: "STANDARD_PORTGROUP",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-n4",
FolderName: "Networks",
HostIDs: []string{"host-101", "host-102", "host-103", "host-104"},
HostNames: []string{"esxi-01.lab.local", "esxi-02.lab.local", "esxi-03.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-201", "vm-202", "vm-203"},
VMNames: []string{"orders-api-01", "postgres-ha-01", "web-frontend-01"},
OverallStatus: "green",
},
{
Network: "network-102",
Name: "Utility Network",
Type: "DISTRIBUTED_PORTGROUP",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-n4",
FolderName: "Networks",
HostIDs: []string{"host-101", "host-103", "host-104"},
HostNames: []string{"esxi-01.lab.local", "esxi-03.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-204", "vm-205"},
VMNames: []string{"observability-01", "windows-jump-01"},
OverallStatus: "yellow",
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-404",
Name: "Distributed portgroup uplink redundancy",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-17 * time.Minute),
}},
},
{
Network: "network-103",
Name: "Archive Network",
Type: "STANDARD_PORTGROUP",
DatacenterID: "datacenter-1",
DatacenterName: "Primary DC",
FolderID: "group-n4",
FolderName: "Networks",
HostIDs: []string{"host-101", "host-104"},
HostNames: []string{"esxi-01.lab.local", "esxi-04.lab.local"},
VMIDs: []string{"vm-206"},
VMNames: []string{"batch-worker-01"},
OverallStatus: "green",
},
},
}
}
// appendEdgeClusterFixtures grows the canonical VMware mock inventory toward
// a mature SMB lab. The edge cluster lives in a second datacenter and adds
// 3 more ESXi hosts, 12 more VMs across a tier-1 application set + a
// stateful tier + a windows fleet, and 4 more datastores (one of each
// canonical storage technology) so the platform-page tables exercise
// grouping, sorting, and responsive density beyond a single small cluster.
func appendEdgeClusterFixtures(
snapshot *InventorySnapshot,
collectedAt time.Time,
accessible bool,
multipleHostAccess bool,
) {
const (
edgeDatacenterID = "datacenter-2"
edgeDatacenterName = "Edge DC"
edgeClusterID = "domain-c201"
edgeClusterName = "Edge Services"
edgeFolderHosts = "group-h6"
edgeFolderHostsLbl = "Edge Cluster Hosts"
edgeFolderVMs = "group-v9"
edgeFolderVMsLbl = "Edge Production VMs"
edgeFolderDS = "group-s6"
edgeFolderDSLbl = "Edge Datastores"
)
edgeHA := true
edgeDRS := false
snapshot.Clusters = append(snapshot.Clusters, InventoryCluster{
Cluster: edgeClusterID,
Name: edgeClusterName,
HAEnabled: &edgeHA,
DRSEnabled: &edgeDRS,
})
edgeDatastoreIDs := []string{"datastore-301", "datastore-302", "datastore-303", "datastore-304"}
edgeDatastoreNames := []string{"edge-nvme-tier", "edge-warm-nfs", "edge-vsan", "edge-cold-iscsi"}
hostSpecs := []struct {
ID string
Name string
UUID string
CPUPct float64
MemPct float64
MemUsed int64
MemTotal int64
Status string
}{
{"host-201", "esxi-05.lab.local", "uuid-host-201", 27.4, 51.6, 44_277_059_584, 85_899_345_920, "green"},
{"host-202", "esxi-06.lab.local", "uuid-host-202", 41.2, 67.9, 58_271_233_120, 85_899_345_920, "green"},
{"host-203", "esxi-07.lab.local", "uuid-host-203", 19.8, 38.4, 32_968_499_584, 85_899_345_920, "yellow"},
}
hostNames := make([]string, 0, len(hostSpecs))
for _, h := range hostSpecs {
hostNames = append(hostNames, h.Name)
}
for _, h := range hostSpecs {
snapshot.Hosts = append(snapshot.Hosts, InventoryHost{
Host: h.ID,
Name: h.Name,
ConnectionState: "CONNECTED",
PowerState: "POWERED_ON",
HostUUID: h.UUID,
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
ComputeResourceID: edgeClusterID,
ComputeResourceName: edgeClusterName,
ClusterID: edgeClusterID,
ClusterName: edgeClusterName,
FolderID: edgeFolderHosts,
FolderName: edgeFolderHostsLbl,
DatastoreIDs: edgeDatastoreIDs,
DatastoreNames: edgeDatastoreNames,
OverallStatus: h.Status,
Metrics: &InventoryMetrics{
CPUPercent: float64Ptr(h.CPUPct),
MemoryPercent: float64Ptr(h.MemPct),
MemoryUsedBytes: int64Ptr(h.MemUsed),
MemoryTotalBytes: int64Ptr(h.MemTotal),
NetInBytesPerSecond: float64Ptr(960_000),
NetOutBytesPerSecond: float64Ptr(820_000),
DiskReadBytesPerSecond: float64Ptr(1_820_000),
DiskWriteBytesPerSecond: float64Ptr(1_540_000),
},
})
}
vmSpecs := []struct {
ID string
Name string
Host string
CPUCount int
MemMiB int64
Tier string
Datastores []string
PowerState string
Status string
Guest string
}{
{"vm-301", "edge-api-01", "host-201", 4, 16 * 1024, "Tier 1", []string{"datastore-301"}, "POWERED_ON", "green", "edge-api-01.internal"},
{"vm-302", "edge-api-02", "host-202", 4, 16 * 1024, "Tier 1", []string{"datastore-301"}, "POWERED_ON", "green", "edge-api-02.internal"},
{"vm-303", "mariadb-replica-01", "host-203", 8, 32 * 1024, "Stateful", []string{"datastore-302"}, "POWERED_ON", "yellow", "mariadb-replica-01.internal"},
{"vm-304", "redis-cache-01", "host-201", 2, 8 * 1024, "Stateful", []string{"datastore-303"}, "POWERED_ON", "green", "redis-cache-01.internal"},
{"vm-305", "redis-cache-02", "host-202", 2, 8 * 1024, "Stateful", []string{"datastore-303"}, "POWERED_ON", "green", "redis-cache-02.internal"},
{"vm-306", "ingress-proxy-01", "host-201", 4, 12 * 1024, "Tier 1", []string{"datastore-301"}, "POWERED_ON", "green", "ingress-proxy-01.internal"},
{"vm-307", "ingress-proxy-02", "host-203", 4, 12 * 1024, "Tier 1", []string{"datastore-301"}, "POWERED_ON", "green", "ingress-proxy-02.internal"},
{"vm-308", "win-fleet-rdp-01", "host-202", 4, 16 * 1024, "Workstations", []string{"datastore-303"}, "POWERED_ON", "green", "win-fleet-rdp-01.lab.local"},
{"vm-309", "win-fleet-rdp-02", "host-203", 4, 16 * 1024, "Workstations", []string{"datastore-303"}, "POWERED_ON", "green", "win-fleet-rdp-02.lab.local"},
{"vm-310", "logging-collector-01", "host-201", 4, 24 * 1024, "Observability", []string{"datastore-302"}, "POWERED_ON", "green", "logging-collector-01.internal"},
{"vm-311", "logging-collector-02", "host-202", 4, 24 * 1024, "Observability", []string{"datastore-302"}, "POWERED_ON", "yellow", "logging-collector-02.internal"},
{"vm-312", "cold-archive-01", "host-203", 2, 8 * 1024, "Archive", []string{"datastore-304"}, "POWERED_OFF", "gray", ""},
}
for _, v := range vmSpecs {
hostName := ""
for _, hs := range hostSpecs {
if hs.ID == v.Host {
hostName = hs.Name
break
}
}
dsNames := make([]string, 0, len(v.Datastores))
for _, dsID := range v.Datastores {
for i, id := range edgeDatastoreIDs {
if id == dsID {
dsNames = append(dsNames, edgeDatastoreNames[i])
}
}
}
cpuPct := 28.0
memPct := 60.0
if v.Status == "yellow" {
cpuPct = 64.0
memPct = 81.0
} else if v.Status == "gray" {
cpuPct = 0
memPct = 0
}
guestIPs := []string{}
if v.PowerState == "POWERED_ON" {
guestIPs = []string{fmt.Sprintf("10.50.20.%d", 10+len(snapshot.VMs))}
}
vm := InventoryVM{
VM: v.ID,
Name: v.Name,
PowerState: v.PowerState,
CPUCount: v.CPUCount,
MemorySizeMiB: v.MemMiB,
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
ComputeResourceID: edgeClusterID,
ComputeResourceName: edgeClusterName,
ClusterID: edgeClusterID,
ClusterName: edgeClusterName,
FolderID: edgeFolderVMs,
FolderName: edgeFolderVMsLbl,
ResourcePoolID: fmt.Sprintf("resgroup-edge-%s", v.Tier),
ResourcePoolName: v.Tier,
RuntimeHostID: v.Host,
RuntimeHostName: hostName,
DatastoreIDs: v.Datastores,
DatastoreNames: dsNames,
InstanceUUID: fmt.Sprintf("vm-instance-%s", v.ID),
BIOSUUID: fmt.Sprintf("vm-bios-%s", v.ID),
GuestOSFamily: guestOSFamily(v.Name),
GuestHostname: v.Guest,
GuestIPAddresses: guestIPs,
OverallStatus: v.Status,
NetworkAdapters: fixtureVMNetworkAdapters(v.ID, edgeVMNetworkName(v.Tier), v.PowerState == "POWERED_ON"),
VirtualDisks: fixtureVMVirtualDisks(v.ID, firstNonEmptyTrimmed(dsNames...), int64(v.MemMiB)*1024*1024*4),
Tools: fixtureVMTools(v.PowerState, v.Status),
Hardware: fixtureVMHardware("UBUNTU_64", "VMX_20", v.PowerState == "POWERED_ON"),
}
if v.PowerState == "POWERED_ON" {
vm.Metrics = &InventoryMetrics{
CPUPercent: float64Ptr(cpuPct),
MemoryPercent: float64Ptr(memPct),
MemoryUsedBytes: int64Ptr(int64(float64(v.MemMiB) * float64(memPct) / 100.0 * 1024 * 1024)),
MemoryTotalBytes: int64Ptr(int64(v.MemMiB) * 1024 * 1024),
NetInBytesPerSecond: float64Ptr(360_000),
NetOutBytesPerSecond: float64Ptr(420_000),
DiskReadBytesPerSecond: float64Ptr(720_000),
DiskWriteBytesPerSecond: float64Ptr(610_000),
}
}
snapshot.VMs = append(snapshot.VMs, vm)
}
type datastoreSpec struct {
ID string
Name string
Type string
Free int64
Cap int64
HostIDs []string
HostName []string
VMIDs []string
VMNames []string
URL string
Status string
}
dsList := []datastoreSpec{
{"datastore-301", "edge-nvme-tier", "VMFS", 3_200_000_000_000, 6_000_000_000_000, []string{"host-201", "host-202", "host-203"}, hostNames, []string{"vm-301", "vm-302", "vm-306", "vm-307"}, []string{"edge-api-01", "edge-api-02", "ingress-proxy-01", "ingress-proxy-02"}, "ds:///vmfs/volumes/datastore-301/", "green"},
{"datastore-302", "edge-warm-nfs", "NFS41", 9_100_000_000_000, 12_000_000_000_000, []string{"host-201", "host-203"}, []string{"esxi-05.lab.local", "esxi-07.lab.local"}, []string{"vm-303", "vm-310", "vm-311"}, []string{"mariadb-replica-01", "logging-collector-01", "logging-collector-02"}, "ds:///nfs/edge-warm-nfs/", "green"},
{"datastore-303", "edge-vsan", "vSAN", 4_900_000_000_000, 9_000_000_000_000, []string{"host-201", "host-202", "host-203"}, hostNames, []string{"vm-304", "vm-305", "vm-308", "vm-309"}, []string{"redis-cache-01", "redis-cache-02", "win-fleet-rdp-01", "win-fleet-rdp-02"}, "ds:///vsan/edge-vsan/", "green"},
{"datastore-304", "edge-cold-iscsi", "VMFS", 18_500_000_000_000, 24_000_000_000_000, []string{"host-202", "host-203"}, []string{"esxi-06.lab.local", "esxi-07.lab.local"}, []string{"vm-312"}, []string{"cold-archive-01"}, "ds:///vmfs/volumes/datastore-304/", "yellow"},
}
for _, ds := range dsList {
snapshot.Datastores = append(snapshot.Datastores, InventoryDatastore{
Datastore: ds.ID,
Name: ds.Name,
Type: ds.Type,
FreeSpace: ds.Free,
Capacity: ds.Cap,
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: edgeFolderDS,
FolderName: edgeFolderDSLbl,
HostIDs: ds.HostIDs,
HostNames: ds.HostName,
VMIDs: ds.VMIDs,
VMNames: ds.VMNames,
Accessible: &accessible,
MultipleHostAccess: &multipleHostAccess,
MaintenanceMode: "normal",
URL: ds.URL,
OverallStatus: ds.Status,
})
}
snapshot.Networks = append(snapshot.Networks,
InventoryNetwork{
Network: "network-301",
Name: "Edge App",
Type: "DISTRIBUTED_PORTGROUP",
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: "group-n6",
FolderName: "Edge Networks",
HostIDs: []string{"host-201", "host-202", "host-203"},
HostNames: hostNames,
VMIDs: []string{"vm-301", "vm-302", "vm-306", "vm-307"},
VMNames: []string{"edge-api-01", "edge-api-02", "ingress-proxy-01", "ingress-proxy-02"},
OverallStatus: "green",
},
InventoryNetwork{
Network: "network-302",
Name: "Edge Stateful",
Type: "DISTRIBUTED_PORTGROUP",
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: "group-n6",
FolderName: "Edge Networks",
HostIDs: []string{"host-201", "host-202", "host-203"},
HostNames: hostNames,
VMIDs: []string{"vm-303", "vm-304", "vm-305"},
VMNames: []string{"mariadb-replica-01", "redis-cache-01", "redis-cache-02"},
OverallStatus: "yellow",
TriggeredAlarms: []InventoryAlarm{{
Alarm: "alarm-405",
Name: "Network packet loss above threshold",
OverallStatus: "yellow",
TriggeredAt: collectedAt.Add(-22 * time.Minute),
}},
},
InventoryNetwork{
Network: "network-303",
Name: "Edge Workstations",
Type: "STANDARD_PORTGROUP",
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: "group-n6",
FolderName: "Edge Networks",
HostIDs: []string{"host-202", "host-203"},
HostNames: []string{"esxi-06.lab.local", "esxi-07.lab.local"},
VMIDs: []string{"vm-308", "vm-309"},
VMNames: []string{"win-fleet-rdp-01", "win-fleet-rdp-02"},
OverallStatus: "green",
},
InventoryNetwork{
Network: "network-304",
Name: "Edge Observability",
Type: "DISTRIBUTED_PORTGROUP",
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: "group-n6",
FolderName: "Edge Networks",
HostIDs: []string{"host-201", "host-202"},
HostNames: []string{"esxi-05.lab.local", "esxi-06.lab.local"},
VMIDs: []string{"vm-310", "vm-311"},
VMNames: []string{"logging-collector-01", "logging-collector-02"},
OverallStatus: "green",
},
InventoryNetwork{
Network: "network-305",
Name: "Edge Archive",
Type: "STANDARD_PORTGROUP",
DatacenterID: edgeDatacenterID,
DatacenterName: edgeDatacenterName,
FolderID: "group-n6",
FolderName: "Edge Networks",
HostIDs: []string{"host-203"},
HostNames: []string{"esxi-07.lab.local"},
VMIDs: []string{"vm-312"},
VMNames: []string{"cold-archive-01"},
OverallStatus: "green",
},
)
}
func applyInventoryClusterServices(snapshot *InventorySnapshot) {
if snapshot == nil {
return
}
clustersByID := inventoryClusterDetailsByID(snapshot.Clusters)
for i := range snapshot.Hosts {
applyClusterServicesToHost(&snapshot.Hosts[i], clustersByID)
}
for i := range snapshot.VMs {
applyClusterServicesToVM(&snapshot.VMs[i], clustersByID)
}
}
func guestOSFamily(name string) string {
if name == "" {
return ""
}
switch name[:3] {
case "win":
return "WINDOWS"
default:
return "LINUX"
}
}
func edgeVMNetworkName(tier string) string {
switch tier {
case "Stateful":
return "Edge Stateful"
case "Archive":
return "Edge Archive"
case "Workstations":
return "Edge Workstations"
case "Observability":
return "Edge Observability"
default:
return "Edge App"
}
}
func fixtureVMNetworkAdapters(vmID, networkName string, connected bool) []InventoryVMNetworkAdapter {
state := "NOT_CONNECTED"
if connected {
state = "CONNECTED"
}
return []InventoryVMNetworkAdapter{{
NIC: "4000",
Label: "Network adapter 1",
Type: "VMXNET3",
MACType: "GENERATED",
MACAddress: fixtureVMMACAddress(vmID),
PCISlotNumber: int64Ptr(160),
BackingType: "STANDARD_PORTGROUP",
NetworkID: "network-" + vmID,
NetworkName: networkName,
State: state,
StartConnected: true,
AllowGuestControl: true,
WakeOnLANEnabled: true,
}}
}
func fixtureVMVirtualDisks(vmID, datastoreName string, capacityBytes int64) []InventoryVMVirtualDisk {
if capacityBytes <= 0 {
capacityBytes = 64_000_000_000
}
datastoreName = firstNonEmptyTrimmed(datastoreName, "vmfs-primary")
return []InventoryVMVirtualDisk{{
Disk: "2000",
Label: "Hard disk 1",
Type: "SCSI",
SCSIBus: int64Ptr(0),
SCSIUnit: int64Ptr(0),
BackingType: "VMDK_FILE",
VMDKFile: fmt.Sprintf("[%s] %s/%s.vmdk", datastoreName, vmID, vmID),
DatastoreName: datastoreName,
CapacityBytes: int64Ptr(capacityBytes),
}}
}
func fixtureVMTools(powerState, status string) *InventoryVMTools {
autoUpdateSupported := true
versionNumber := int64(12352)
runState := "RUNNING"
versionStatus := "CURRENT"
if powerState != "POWERED_ON" {
runState = "NOT_RUNNING"
}
if status == "yellow" {
versionStatus = "SUPPORTED_OLD"
}
return &InventoryVMTools{
AutoUpdateSupported: boolPointer(autoUpdateSupported),
VersionNumber: &versionNumber,
Version: "12.4.0",
UpgradePolicy: "MANUAL",
VersionStatus: versionStatus,
InstallType: "OPEN_VM_TOOLS",
RunState: runState,
}
}
func fixtureVMHardware(guestOS, version string, hotAddEnabled bool) *InventoryVMHardware {
instantCloneFrozen := false
efiLegacyBoot := false
bootDelayMilliseconds := int64(0)
bootRetry := false
bootRetryDelayMilliseconds := int64(10000)
enterSetupMode := false
coresPerSocket := int64(2)
memoryHotAddIncrementMiB := int64(256)
memoryHotAddLimitMiB := int64(16 * 1024)
return &InventoryVMHardware{
GuestOS: guestOS,
InstantCloneFrozen: boolPointer(instantCloneFrozen),
Version: version,
UpgradePolicy: "NEVER",
UpgradeStatus: "NONE",
BootType: "EFI",
EFILegacyBoot: &efiLegacyBoot,
BootNetworkProtocol: "IPV4",
BootDelayMilliseconds: &bootDelayMilliseconds,
BootRetry: &bootRetry,
BootRetryDelayMilliseconds: &bootRetryDelayMilliseconds,
EnterSetupMode: &enterSetupMode,
BootDevices: []InventoryVMBootDevice{{
Type: "DISK",
Disks: []string{"2000"},
}},
CPUCoresPerSocket: &coresPerSocket,
CPUHotAddEnabled: boolPointer(hotAddEnabled),
CPUHotRemoveEnabled: boolPointer(false),
MemoryHotAddEnabled: boolPointer(hotAddEnabled),
MemoryHotAddIncrementMiB: &memoryHotAddIncrementMiB,
MemoryHotAddLimitMiB: &memoryHotAddLimitMiB,
}
}
func boolPointer(value bool) *bool {
return &value
}
func fixtureVMMACAddress(vmID string) string {
var value int
for _, r := range vmID {
value += int(r)
}
return fmt.Sprintf("00:50:56:%02x:%02x:%02x", (value>>8)&0xff, value&0xff, (value+37)&0xff)
}
func inventorySnapshotTime(value time.Time) *time.Time {
timestamp := value.UTC()
return &timestamp
}