diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 97e057af283..642049738fb 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -319,6 +319,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] - Add SSL support to mysql module {pull}37997[37997] - Add SSL support for aerospike module {pull}38126[38126] - Add new metricset network for the vSphere module. {pull}40559[40559] +- Add new metricset resourcepool for the vSphere module. {pull}40456[40456] *Metricbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 6e89e720d39..6a626d44cae 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -67519,6 +67519,232 @@ type: long -- +[float] +=== resourcepool + +Resource pool information from vSphere environment. + + + + +*`vsphere.resourcepool.cpu.usage.mhz`*:: ++ +-- +Basic CPU performance statistics, in MHz. + + +type: long + +-- + +*`vsphere.resourcepool.cpu.demand.mhz`*:: ++ +-- +Basic CPU performance statistics, in MHz. + + +type: long + +-- + + +*`vsphere.resourcepool.cpu.entitlement.mhz`*:: ++ +-- +The amount of CPU resource, in MHz, that this VM is entitled to, as calculated by DRS. + + +type: long + +-- + +*`vsphere.resourcepool.cpu.entitlement.static.mhz`*:: ++ +-- +The static CPU resource entitlement for a virtual machine. + + +type: long + +-- + + + +*`vsphere.resourcepool.memory.usage.guest.bytes`*:: ++ +-- +Guest memory utilization statistics, in bytes. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.usage.host.bytes`*:: ++ +-- +Host memory utilization statistics, in bytes. + + +type: long + +format: bytes + +-- + + +*`vsphere.resourcepool.memory.entitlement.bytes`*:: ++ +-- +The amount of memory, in bytes, that this VM is entitled to, as calculated by DRS. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.entitlement.static.bytes`*:: ++ +-- +The static memory resource entitlement for a virtual machine, in bytes. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.private.bytes`*:: ++ +-- +The portion of memory, in bytes, that is granted to a virtual machine from non-shared host memory. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.shared.bytes`*:: ++ +-- +The portion of memory, in bytes, that is granted to a virtual machine from host memory that is shared between VMs. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.swapped.bytes`*:: ++ +-- +The portion of memory, in bytes, that is granted to a virtual machine from the host's swap space. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.ballooned.bytes`*:: ++ +-- +The size of the balloon driver in a virtual machine, in bytes. + + +type: long + +format: bytes + +-- + + +*`vsphere.resourcepool.memory.overhead.bytes`*:: ++ +-- +The amount of memory resource (in bytes) that will be used by a virtual machine above its guest memory requirements. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.overhead.consumed.bytes`*:: ++ +-- +The amount of overhead memory, in bytes, currently being consumed to run a VM. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.memory.compressed.bytes`*:: ++ +-- +The amount of compressed memory currently consumed by VM, in bytes. + + +type: long + +format: bytes + +-- + +*`vsphere.resourcepool.name`*:: ++ +-- +The name of the resource pool. + + +type: keyword + +-- + +*`vsphere.resourcepool.status`*:: ++ +-- +The overall health status of a host in the vSphere environment. + + +type: keyword + +-- + + +*`vsphere.resourcepool.vm.count`*:: ++ +-- +Number of virtual machines on the resource pool. + + +type: long + +-- + +*`vsphere.resourcepool.vm.names`*:: ++ +-- +Names of virtual machines on the resource pool. + + +type: keyword + +-- + [float] === virtualmachine diff --git a/metricbeat/docs/modules/vsphere.asciidoc b/metricbeat/docs/modules/vsphere.asciidoc index fe19eab1459..746a3d98dc8 100644 --- a/metricbeat/docs/modules/vsphere.asciidoc +++ b/metricbeat/docs/modules/vsphere.asciidoc @@ -11,7 +11,7 @@ This file is generated! See scripts/mage/docs_collector.go The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. -By default it enables the metricsets `network`, `datastore`, `host` and `virtualmachine`. +By default it enables the metricsets `network`, `resourcepool`, `datastore`, `host` and `virtualmachine`. [float] === Dashboard @@ -35,7 +35,7 @@ in <>. Here is an example configuration: metricbeat.modules: - module: vsphere enabled: true - metricsets: ["datastore", "host", "virtualmachine", "network"] + metricsets: ["datastore", "host", "virtualmachine", "network", "resourcepool"] # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"] @@ -59,6 +59,8 @@ The following metricsets are available: * <> +* <> + * <> include::vsphere/datastore.asciidoc[] @@ -67,6 +69,8 @@ include::vsphere/host.asciidoc[] include::vsphere/network.asciidoc[] +include::vsphere/resourcepool.asciidoc[] + include::vsphere/virtualmachine.asciidoc[] :edit_url!: diff --git a/metricbeat/docs/modules/vsphere/resourcepool.asciidoc b/metricbeat/docs/modules/vsphere/resourcepool.asciidoc new file mode 100644 index 00000000000..8bec0604b53 --- /dev/null +++ b/metricbeat/docs/modules/vsphere/resourcepool.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/metricbeat/module/vsphere/resourcepool/_meta/docs.asciidoc + + +[[metricbeat-metricset-vsphere-resourcepool]] +=== vSphere resourcepool metricset + +beta[] + +include::../../../module/vsphere/resourcepool/_meta/docs.asciidoc[] + +This is a default metricset. If the host module is unconfigured, this metricset is enabled by default. + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/vsphere/resourcepool/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index fd32d6c1fc4..1942747c02c 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -311,9 +311,10 @@ This file is generated! See scripts/mage/docs_collector.go |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | .1+| .1+| |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | -.4+| .4+| |<> +.5+| .5+| |<> |<> |<> beta[] +|<> beta[] |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | .2+| .2+| |<> diff --git a/metricbeat/include/list_common.go b/metricbeat/include/list_common.go index 27b976e9c30..0b8226ed3ce 100644 --- a/metricbeat/include/list_common.go +++ b/metricbeat/include/list_common.go @@ -184,6 +184,7 @@ import ( _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/datastore" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/host" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/network" + _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/resourcepool" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/virtualmachine" _ "github.com/elastic/beats/v7/metricbeat/module/windows" _ "github.com/elastic/beats/v7/metricbeat/module/windows/perfmon" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index d39f3c489ed..c82182c12ea 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1007,7 +1007,7 @@ metricbeat.modules: #------------------------------- VSphere Module ------------------------------- - module: vsphere enabled: true - metricsets: ["datastore", "host", "virtualmachine", "network"] + metricsets: ["datastore", "host", "virtualmachine", "network", "resourcepool"] # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"] diff --git a/metricbeat/module/vsphere/_meta/README.md b/metricbeat/module/vsphere/_meta/README.md index 19ddad7fd25..8af88a660af 100644 --- a/metricbeat/module/vsphere/_meta/README.md +++ b/metricbeat/module/vsphere/_meta/README.md @@ -32,6 +32,7 @@ Now setup your metricbeat config to connect to Govcsim: - host - virtualmachine - network + - resourcepool enabled: true period: 5s hosts: ["https://127.0.0.1:8989/sdk"] diff --git a/metricbeat/module/vsphere/_meta/config.reference.yml b/metricbeat/module/vsphere/_meta/config.reference.yml index 7d4344b72e7..d3fc63eb1e2 100644 --- a/metricbeat/module/vsphere/_meta/config.reference.yml +++ b/metricbeat/module/vsphere/_meta/config.reference.yml @@ -1,6 +1,6 @@ - module: vsphere enabled: true - metricsets: ["datastore", "host", "virtualmachine", "network"] + metricsets: ["datastore", "host", "virtualmachine", "network", "resourcepool"] # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"] diff --git a/metricbeat/module/vsphere/_meta/config.yml b/metricbeat/module/vsphere/_meta/config.yml index 4586904afc2..dc7617b155b 100644 --- a/metricbeat/module/vsphere/_meta/config.yml +++ b/metricbeat/module/vsphere/_meta/config.yml @@ -4,6 +4,7 @@ # - host # - virtualmachine # - network + # - resourcepool # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"] diff --git a/metricbeat/module/vsphere/_meta/docs.asciidoc b/metricbeat/module/vsphere/_meta/docs.asciidoc index 44b4e7d340a..96262ffed8d 100644 --- a/metricbeat/module/vsphere/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/_meta/docs.asciidoc @@ -1,6 +1,6 @@ The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. -By default it enables the metricsets `network`, `datastore`, `host` and `virtualmachine`. +By default it enables the metricsets `network`, `resourcepool`, `datastore`, `host` and `virtualmachine`. [float] === Dashboard diff --git a/metricbeat/module/vsphere/fields.go b/metricbeat/module/vsphere/fields.go index a443e27d7d1..62941aa3afc 100644 --- a/metricbeat/module/vsphere/fields.go +++ b/metricbeat/module/vsphere/fields.go @@ -32,5 +32,5 @@ func init() { // AssetVsphere returns asset data. // This is the base64 encoded zlib format compressed contents of module/vsphere. func AssetVsphere() string { - return "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" + return "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" } diff --git a/metricbeat/module/vsphere/resourcepool/_meta/data.json b/metricbeat/module/vsphere/resourcepool/_meta/data.json new file mode 100644 index 00000000000..a16e9d59197 --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/_meta/data.json @@ -0,0 +1,77 @@ +{ + "@timestamp": "2024-08-06T10:38:51.952Z", + "metricset": { + "name": "resourcepool", + "period": 10000 + }, + "service": { + "type": "vsphere", + "address": "https://localhost:8989/sdk" + }, + "event": { + "dataset": "vsphere.resourcepool", + "module": "vsphere", + "duration": 57462824 + }, + "vsphere": { + "resourcepool": { + "name": "Resources", + "status": "green", + "vm": { + "names": ["DC0_H0_VM0", "DC0_H0_VM1"], + "count": 2 + }, + "cpu": { + "usage": { + "mhz": 3323 + }, + "demand": { + "mhz": 3344 + }, + "entitlement": { + "mhz": 3197, + "static": { + "mhz": 21294 + } + } + }, + "memory": { + "compressed": { + "bytes": 0 + }, + "usage": { + "guest": { + "bytes": 6515851264 + }, + "host": { + "bytes": 122227261440 + } + }, + "entitlement": { + "bytes": 38726008832, + "static": { + "bytes": 14680064 + } + }, + "private": { + "bytes": 121226919936 + }, + "shared": { + "bytes": 45088768 + }, + "swapped": { + "bytes": 0 + }, + "ballooned": { + "bytes": 0 + }, + "overhead": { + "bytes": 1695547392, + "consumed": { + "bytes": 1001390080 + } + } + } + } + } +} diff --git a/metricbeat/module/vsphere/resourcepool/_meta/docs.asciidoc b/metricbeat/module/vsphere/resourcepool/_meta/docs.asciidoc new file mode 100644 index 00000000000..f155e599a93 --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the resourcepool metricset of the module vsphere. diff --git a/metricbeat/module/vsphere/resourcepool/_meta/fields.yml b/metricbeat/module/vsphere/resourcepool/_meta/fields.yml new file mode 100644 index 00000000000..8b376d34472 --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/_meta/fields.yml @@ -0,0 +1,114 @@ +- name: resourcepool + type: group + release: beta + description: > + Resource pool information from vSphere environment. + fields: + - name: cpu + type: group + fields: + - name: usage.mhz + type: long + description: > + Basic CPU performance statistics, in MHz. + - name: demand.mhz + type: long + description: > + Basic CPU performance statistics, in MHz. + - name: entitlement + type: group + fields: + - name: mhz + type: long + description: > + The amount of CPU resource, in MHz, that this VM is entitled to, as calculated by DRS. + - name: static.mhz + type: long + description: > + The static CPU resource entitlement for a virtual machine. + - name: memory + type: group + fields: + - name: usage + type: group + fields: + - name: guest.bytes + type: long + description: > + Guest memory utilization statistics, in bytes. + format: bytes + - name: host.bytes + type: long + description: > + Host memory utilization statistics, in bytes. + format: bytes + - name: entitlement + type: group + fields: + - name: bytes + type: long + description: > + The amount of memory, in bytes, that this VM is entitled to, as calculated by DRS. + format: bytes + - name: static.bytes + type: long + description: > + The static memory resource entitlement for a virtual machine, in bytes. + format: bytes + - name: private.bytes + type: long + description: > + The portion of memory, in bytes, that is granted to a virtual machine from non-shared host memory. + format: bytes + - name: shared.bytes + type: long + description: > + The portion of memory, in bytes, that is granted to a virtual machine from host memory that is shared between VMs. + format: bytes + - name: swapped.bytes + type: long + description: > + The portion of memory, in bytes, that is granted to a virtual machine from the host's swap space. + format: bytes + - name: ballooned.bytes + type: long + description: > + The size of the balloon driver in a virtual machine, in bytes. + format: bytes + - name: overhead + type: group + fields: + - name: bytes + type: long + description: > + The amount of memory resource (in bytes) that will be used by a virtual machine above its guest memory requirements. + format: bytes + - name: consumed.bytes + type: long + description: > + The amount of overhead memory, in bytes, currently being consumed to run a VM. + format: bytes + - name: compressed.bytes + type: long + description: > + The amount of compressed memory currently consumed by VM, in bytes. + format: bytes + - name: name + type: keyword + description: > + The name of the resource pool. + - name: status + type: keyword + description: > + The overall health status of a host in the vSphere environment. + - name: vm + type: group + fields: + - name: count + type: long + description: > + Number of virtual machines on the resource pool. + - name: names + type: keyword + description: > + Names of virtual machines on the resource pool. diff --git a/metricbeat/module/vsphere/resourcepool/data.go b/metricbeat/module/vsphere/resourcepool/data.go new file mode 100644 index 00000000000..c63c1883478 --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/data.go @@ -0,0 +1,64 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package resourcepool + +import ( + "github.com/vmware/govmomi/vim25/mo" + + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const ( + mbToBytes = 1024 * 1024 + kbToBytes = 1024 +) + +func (m *ResourcePoolMetricSet) mapEvent(rp mo.ResourcePool, data *metricData) mapstr.M { + event := mapstr.M{ + "name": rp.Name, + "status": rp.OverallStatus, + } + + quickStats := rp.Summary.GetResourcePoolSummary().QuickStats + if quickStats == nil { + return event + } + + event.Put("cpu.usage.mhz", quickStats.OverallCpuUsage) + event.Put("cpu.demand.mhz", quickStats.OverallCpuDemand) + event.Put("cpu.entitlement.mhz", quickStats.DistributedCpuEntitlement) + event.Put("cpu.entitlement.static.mhz", quickStats.StaticCpuEntitlement) + event.Put("memory.usage.guest.bytes", quickStats.GuestMemoryUsage*mbToBytes) + event.Put("memory.usage.host.bytes", quickStats.HostMemoryUsage*mbToBytes) + event.Put("memory.entitlement.bytes", quickStats.DistributedMemoryEntitlement*mbToBytes) + event.Put("memory.entitlement.static.bytes", quickStats.StaticMemoryEntitlement*mbToBytes) + event.Put("memory.private.bytes", quickStats.PrivateMemory*mbToBytes) + event.Put("memory.shared.bytes", quickStats.SharedMemory*mbToBytes) + event.Put("memory.swapped.bytes", quickStats.SwappedMemory*mbToBytes) + event.Put("memory.ballooned.bytes", quickStats.BalloonedMemory*mbToBytes) + event.Put("memory.overhead.bytes", quickStats.OverheadMemory*mbToBytes) + event.Put("memory.overhead.consumed.bytes", quickStats.ConsumedOverheadMemory*mbToBytes) + event.Put("memory.compressed.bytes", quickStats.CompressedMemory*kbToBytes) + + if len(data.assetNames.outputVmNames) > 0 { + event.Put("vm.names", data.assetNames.outputVmNames) + event.Put("vm.count", len(data.assetNames.outputVmNames)) + } + + return event +} diff --git a/metricbeat/module/vsphere/resourcepool/data_test.go b/metricbeat/module/vsphere/resourcepool/data_test.go new file mode 100644 index 00000000000..ce7ccec484e --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/data_test.go @@ -0,0 +1,120 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package resourcepool + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" +) + +func TestEventMapping(t *testing.T) { + var m *ResourcePoolMetricSet + resourcePoolTest := mo.ResourcePool{ + ManagedEntity: mo.ManagedEntity{ + OverallStatus: "green", + Name: "resourcepool-test", + }, + Summary: &types.ResourcePoolSummary{ + QuickStats: &types.ResourcePoolQuickStats{ + OverallCpuUsage: 100, + OverallCpuDemand: 100, + GuestMemoryUsage: 100 * mbToBytes, + HostMemoryUsage: 70 * mbToBytes, + DistributedCpuEntitlement: 50, + DistributedMemoryEntitlement: 50 * mbToBytes, + StaticCpuEntitlement: 40, + StaticMemoryEntitlement: 78 * mbToBytes, + PrivateMemory: 10 * mbToBytes, + SharedMemory: 20 * mbToBytes, + SwappedMemory: 30 * mbToBytes, + BalloonedMemory: 40 * mbToBytes, + OverheadMemory: 50 * mbToBytes, + ConsumedOverheadMemory: 60 * mbToBytes, + CompressedMemory: 70 * kbToBytes, + }, + }, + } + + var metricDataTest = metricData{ + assetNames: assetNames{ + outputVmNames: []string{"vm-1", "vm-2"}, + }, + } + + event := m.mapEvent(resourcePoolTest, &metricDataTest) // Ensure this is within a function + + vmName, _ := event.GetValue("vm.names") + assert.EqualValues(t, metricDataTest.assetNames.outputVmNames, vmName) + + vmCount, _ := event.GetValue("vm.count") + assert.EqualValues(t, vmCount, len(metricDataTest.assetNames.outputVmNames)) + + status, _ := event.GetValue("status") + assert.EqualValues(t, "green", status) + + name := event["name"].(string) + assert.EqualValues(t, name, "resourcepool-test") + + cpuUsage, _ := event.GetValue("cpu.usage.mhz") + assert.GreaterOrEqual(t, cpuUsage, int64(0)) + + cpuDemand, _ := event.GetValue("cpu.demand.mhz") + assert.GreaterOrEqual(t, cpuDemand, int64(0)) + + guestMemoryUsage, _ := event.GetValue("memory.usage.guest.bytes") + assert.GreaterOrEqual(t, guestMemoryUsage, int64(0)) + + hostMemoryUsage, _ := event.GetValue("memory.usage.host.bytes") + assert.GreaterOrEqual(t, hostMemoryUsage, int64(0)) + + cpuEntitlement, _ := event.GetValue("cpu.entitlement.mhz") + assert.GreaterOrEqual(t, cpuEntitlement, int64(0)) + + memoryEntitlement, _ := event.GetValue("memory.entitlement.bytes") + assert.GreaterOrEqual(t, memoryEntitlement, int64(0)) + + cpuStaticEntitlement, _ := event.GetValue("cpu.entitlement.static.mhz") + assert.GreaterOrEqual(t, cpuStaticEntitlement, int32(0)) + + memoryStaticEntitlement, _ := event.GetValue("memory.entitlement.static.bytes") + assert.GreaterOrEqual(t, memoryStaticEntitlement, int32(0)) + + memoryPrivate, _ := event.GetValue("memory.private.bytes") + assert.GreaterOrEqual(t, memoryPrivate, int64(0)) + + memoryShared, _ := event.GetValue("memory.shared.bytes") + assert.GreaterOrEqual(t, memoryShared, int64(0)) + + memorySwapped, _ := event.GetValue("memory.swapped.bytes") + assert.GreaterOrEqual(t, memorySwapped, int64(0)) + + memoryBallooned, _ := event.GetValue("memory.ballooned.bytes") + assert.GreaterOrEqual(t, memoryBallooned, int64(0)) + + memoryOverhead, _ := event.GetValue("memory.overhead.bytes") + assert.GreaterOrEqual(t, memoryOverhead, int64(0)) + + memoryOverheadConsumed, _ := event.GetValue("memory.overhead.consumed.bytes") + assert.GreaterOrEqual(t, memoryOverheadConsumed, int64(0)) + + memoryCompressed, _ := event.GetValue("memory.compressed.bytes") + assert.GreaterOrEqual(t, memoryCompressed, int64(0)) +} diff --git a/metricbeat/module/vsphere/resourcepool/resourcepool.go b/metricbeat/module/vsphere/resourcepool/resourcepool.go new file mode 100644 index 00000000000..ed54b6907fd --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/resourcepool.go @@ -0,0 +1,150 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package resourcepool + +import ( + "context" + "fmt" + "strings" + + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/view" + "github.com/vmware/govmomi/vim25/mo" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/metricbeat/module/vsphere" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each resourcepool is defined in the module's configuration. After the +// MetricSet has been created, Fetch will be called periodically. +func init() { + mb.Registry.MustAddMetricSet("vsphere", "resourcepool", New, + mb.WithHostParser(vsphere.HostParser), + mb.DefaultMetricSet(), + ) +} + +// ResourcePoolMetricSet type defines all fields of the MetricSet. +type ResourcePoolMetricSet struct { + *vsphere.MetricSet +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + ms, err := vsphere.NewMetricSet(base) + if err != nil { + return nil, err + } + return &ResourcePoolMetricSet{ms}, nil +} + +// metricData holds performance metrics values. +type metricData struct { + assetNames assetNames +} + +type assetNames struct { + outputVmNames []string +} + +// Fetch methods implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *ResourcePoolMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + client, err := govmomi.NewClient(ctx, m.HostURL, m.Insecure) + if err != nil { + return fmt.Errorf("error in NewClient: %w", err) + } + + defer func() { + if err := client.Logout(ctx); err != nil { + m.Logger().Errorf("error trying to log out from vSphere: %w", err) + } + }() + + c := client.Client + + // Create a view of ResourcePool objects. + mgr := view.NewManager(c) + + v, err := mgr.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"ResourcePool"}, true) + if err != nil { + return fmt.Errorf("error in CreateContainerView: %w", err) + } + + defer func() { + if err := v.Destroy(ctx); err != nil { + m.Logger().Errorf("error trying to destroy view from vSphere: %w", err) + } + }() + + // Retrieve property for all ResourcePools. + var rps []mo.ResourcePool + err = v.Retrieve(ctx, []string{"ResourcePool"}, []string{"name", "overallStatus", "vm", "summary"}, &rps) + if err != nil { + return fmt.Errorf("error in Retrieve: %w", err) + } + + pc := property.DefaultCollector(c) + for i := range rps { + select { + case <-ctx.Done(): + return ctx.Err() + default: + assetNames, err := getAssetNames(ctx, pc, &rps[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from resource pool %s: %w", rps[i].Name, err) + } + + reporter.Event(mb.Event{ + MetricSetFields: m.mapEvent(rps[i], &metricData{assetNames: assetNames}), + }) + } + } + + return nil +} + +func getAssetNames(ctx context.Context, pc *property.Collector, rp *mo.ResourcePool) (assetNames, error) { + if len(rp.Vm) == 0 { + return assetNames{}, nil + } + + var objects []mo.ManagedEntity + err := pc.Retrieve(ctx, rp.Vm, []string{"name"}, &objects) + if err != nil { + return assetNames{}, err + } + + outputVmNames := make([]string, 0, len(objects)) + for _, ob := range objects { + if ob.Reference().Type == "VirtualMachine" { + name := strings.ReplaceAll(ob.Name, ".", "_") + outputVmNames = append(outputVmNames, name) + } + } + + return assetNames{outputVmNames: outputVmNames}, nil +} diff --git a/metricbeat/module/vsphere/resourcepool/resourcepool_test.go b/metricbeat/module/vsphere/resourcepool/resourcepool_test.go new file mode 100644 index 00000000000..d3aecccebb6 --- /dev/null +++ b/metricbeat/module/vsphere/resourcepool/resourcepool_test.go @@ -0,0 +1,106 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package resourcepool + +import ( + "testing" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/vmware/govmomi/simulator" +) + +func TestFetchEventContents(t *testing.T) { + model := simulator.VPX() + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) + + ts := model.Service.NewServer() + t.Cleanup(func() { ts.Close() }) + + f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) + events, errs := mbtest.ReportingFetchV2WithContext(f) + require.Empty(t, errs, "expected no error") + + require.NotEmpty(t, events, "didn't get any event, should have gotten at least X") + + event := events[0].MetricSetFields + + t.Logf("Fetched event from %s/%s event: %+v", f.Module().Name(), f.Name(), event) + + assert.EqualValues(t, "Resources", event["name"]) + assert.EqualValues(t, "green", event["status"]) + + if vm, ok := event["vm"].(mapstr.M); ok { + assert.NotNil(t, vm["names"]) + assert.GreaterOrEqual(t, vm["count"], 0) + } + + if cpu, ok := event["cpu"].(mapstr.M); ok { + assert.GreaterOrEqual(t, cpu["usage.mhz"], 0) + assert.GreaterOrEqual(t, cpu["demand.mhz"], 0) + assert.GreaterOrEqual(t, cpu["entitlement.mhz"], 0) + assert.GreaterOrEqual(t, cpu["static.entitlement.mhz"], 0) + } + + if memory, ok := event["memory"].(mapstr.M); ok { + assert.GreaterOrEqual(t, memory["usage.guest.mb"], 0) + assert.GreaterOrEqual(t, memory["usage.host.mb"], 0) + assert.GreaterOrEqual(t, memory["entitlement.mb"], 0) + assert.GreaterOrEqual(t, memory["static.entitlement.bytes"], 0) + assert.GreaterOrEqual(t, memory["private.mb"], 0) + assert.GreaterOrEqual(t, memory["shared.mb"], 0) + assert.GreaterOrEqual(t, memory["swapped.mb"], 0) + assert.GreaterOrEqual(t, memory["ballooned.mb"], 0) + assert.GreaterOrEqual(t, memory["overhead.mb"], 0) + assert.GreaterOrEqual(t, memory["overhead.consumed.mb"], 0) + assert.GreaterOrEqual(t, memory["compressed.mb"], 0) + } +} + +func TestResourcePoolMetricSetData(t *testing.T) { + model := simulator.VPX() + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) + + ts := model.Service.NewServer() + t.Cleanup(func() { ts.Close() }) + + f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) + + err = mbtest.WriteEventsReporterV2WithContext(f, t, "") + assert.NoError(t, err, "failed to write events with reporter") +} + +func getConfig(ts *simulator.Server) map[string]interface{} { + urlSimulator := ts.URL.Scheme + "://" + ts.URL.Host + ts.URL.Path + + return map[string]interface{}{ + "module": "vsphere", + "metricsets": []string{"resourcepool"}, + "hosts": []string{urlSimulator}, + "username": "user", + "password": "pass", + "insecure": true, + } +} diff --git a/metricbeat/modules.d/vsphere.yml.disabled b/metricbeat/modules.d/vsphere.yml.disabled index 3611bbe5a56..4a05170dd05 100644 --- a/metricbeat/modules.d/vsphere.yml.disabled +++ b/metricbeat/modules.d/vsphere.yml.disabled @@ -7,6 +7,7 @@ # - host # - virtualmachine # - network + # - resourcepool # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"] diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index 4995b469203..ce703584877 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -1568,7 +1568,7 @@ metricbeat.modules: #------------------------------- VSphere Module ------------------------------- - module: vsphere enabled: true - metricsets: ["datastore", "host", "virtualmachine", "network"] + metricsets: ["datastore", "host", "virtualmachine", "network", "resourcepool"] # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. period: 20s hosts: ["https://localhost/sdk"]