| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | package vsphere |
| 4 | |
| 5 | import ( |
| 6 | "context" |
| 7 | "testing" |
| 8 | |
| 9 | "github.com/stretchr/testify/require" |
| 10 | "github.com/vmware/govmomi/performance" |
| 11 | |
| 12 | "github.com/netdata/netdata/go/plugins/pkg/metrix" |
| 13 | rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources" |
| 14 | "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest" |
| 15 | ) |
| 16 | |
| 17 | func TestCollector_PowerMetricsEmitCharts(t *testing.T) { |
| 18 | collr, _, teardown := prepareVSphereSim(t) |
| 19 | defer teardown() |
| 20 | |
| 21 | require.NoError(t, collr.Init(context.Background())) |
| 22 | host := firstSortedHost(t, collr) |
| 23 | vm := firstSortedVM(t, collr) |
| 24 | collr.scraper = mockPowerMetricsScraper{ |
| 25 | mockScraper: mockScraper{collr.scraper}, |
| 26 | hostID: host.ID, |
| 27 | vmID: vm.ID, |
| 28 | hostSeries: testHostPowerSeries(), |
| 29 | vmSeries: testVMPowerSeries(), |
| 30 | } |
| 31 | |
| 32 | require.NotEmpty(t, collectScalarSeriesForTest(t, collr)) |
| 33 | |
| 34 | reader := collr.MetricStore().Read(metrix.ReadRaw()) |
| 35 | hostLabels := hostPowerLabelsMap(collr, host) |
| 36 | requireMetricValue(t, reader, hostPowerUsagePowerMetric, hostLabels, 101) |
| 37 | requireMetricValue(t, reader, hostPowerUsageCapMetric, hostLabels, 102) |
| 38 | requireMetricValue(t, reader, hostPowerCapacityUsageUsedMetric, hostLabels, 103) |
| 39 | requireMetricValue(t, reader, hostPowerCapacityUsageUsableMetric, hostLabels, 104) |
| 40 | requireMetricValue(t, reader, hostPowerCapacityUsageIdleMetric, hostLabels, 105) |
| 41 | requireMetricValue(t, reader, hostPowerCapacityUsageSystemMetric, hostLabels, 106) |
| 42 | requireMetricValue(t, reader, hostPowerCapacityUsageVMMetric, hostLabels, 107) |
| 43 | requireMetricValue(t, reader, hostPowerCapacityUtilizationMetric, hostLabels, 108) |
| 44 | requireMetricValue(t, reader, hostEnergyUsageMetric, hostLabels, 109) |
| 45 | |
| 46 | vmLabels := vmPowerLabelsMap(collr, vm) |
| 47 | requireMetricValue(t, reader, vmPowerUsagePowerMetric, vmLabels, 201) |
| 48 | requireMetricValue(t, reader, vmEnergyUsageMetric, vmLabels, 202) |
| 49 | |
| 50 | createdCharts, createdDims := v2CreatedChartsAndDims(buildV2PlanForTest(t, collr)) |
| 51 | hostPowerChartID := findChartIDByLabelsAndContext(t, createdCharts, "vsphere.host_power_usage", map[string]string{ |
| 52 | "id": host.ID, |
| 53 | }) |
| 54 | require.Contains(t, createdDims[hostPowerChartID], "power") |
| 55 | require.Contains(t, createdDims[hostPowerChartID], "cap") |
| 56 | |
| 57 | vmPowerChartID := findChartIDByLabelsAndContext(t, createdCharts, "vsphere.vm_power_usage", map[string]string{ |
| 58 | "id": vm.ID, |
| 59 | }) |
| 60 | require.Contains(t, createdDims[vmPowerChartID], "power") |
| 61 | collecttest.AssertChartCoverage(t, collr, collecttest.ChartCoverageExpectation{}) |
| 62 | requireChartSelectorsMatchSeries(t, collr, |
| 63 | "vsphere.host_power_", |
| 64 | "vsphere.host_energy_usage", |
| 65 | "vsphere.vm_power_usage", |
| 66 | "vsphere.vm_energy_usage", |
| 67 | ) |
| 68 | } |
| 69 | |
| 70 | type mockPowerMetricsScraper struct { |
| 71 | mockScraper |
| 72 | hostID string |
| 73 | vmID string |
| 74 | hostSeries []performance.MetricSeries |
| 75 | vmSeries []performance.MetricSeries |
| 76 | } |
| 77 | |
| 78 | func (s mockPowerMetricsScraper) ScrapeHosts(hosts rs.Hosts) []performance.EntityMetric { |
| 79 | host := hosts.Get(s.hostID) |
| 80 | if host == nil { |
| 81 | return nil |
| 82 | } |
| 83 | return []performance.EntityMetric{{ |
| 84 | Entity: host.Ref, |
| 85 | Value: append([]performance.MetricSeries(nil), s.hostSeries...), |
| 86 | }} |
| 87 | } |
| 88 | |
| 89 | func (s mockPowerMetricsScraper) ScrapeVMs(vms rs.VMs) []performance.EntityMetric { |
| 90 | vm := vms.Get(s.vmID) |
| 91 | if vm == nil { |
| 92 | return nil |
| 93 | } |
| 94 | return []performance.EntityMetric{{ |
| 95 | Entity: vm.Ref, |
| 96 | Value: append([]performance.MetricSeries(nil), s.vmSeries...), |
| 97 | }} |
| 98 | } |
| 99 | |
| 100 | func testHostPowerSeries() []performance.MetricSeries { |
| 101 | return []performance.MetricSeries{ |
| 102 | {Name: "power.power.average", Value: []int64{101}}, |
| 103 | {Name: "power.powerCap.average", Value: []int64{102}}, |
| 104 | {Name: "power.capacity.usage.average", Value: []int64{103}}, |
| 105 | {Name: "power.capacity.usable.average", Value: []int64{104}}, |
| 106 | {Name: "power.capacity.usageIdle.average", Value: []int64{105}}, |
| 107 | {Name: "power.capacity.usageSystem.average", Value: []int64{106}}, |
| 108 | {Name: "power.capacity.usageVm.average", Value: []int64{107}}, |
| 109 | {Name: "power.capacity.usagePct.average", Value: []int64{108}}, |
| 110 | {Name: "power.energy.summation", Value: []int64{109}}, |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | func testVMPowerSeries() []performance.MetricSeries { |
| 115 | return []performance.MetricSeries{ |
| 116 | {Name: "power.power.average", Value: []int64{201}}, |
| 117 | {Name: "power.energy.summation", Value: []int64{202}}, |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | func hostPowerLabelsMap(collr *Collector, host *rs.Host) metrix.Labels { |
| 122 | labels := make(metrix.Labels) |
| 123 | for _, label := range collr.hostPowerLabels(host) { |
| 124 | labels[label.Key] = label.Value |
| 125 | } |
| 126 | return labels |
| 127 | } |
| 128 | |
| 129 | func vmPowerLabelsMap(collr *Collector, vm *rs.VM) metrix.Labels { |
| 130 | labels := make(metrix.Labels) |
| 131 | for _, label := range collr.vmPowerLabels(vm) { |
| 132 | labels[label.Key] = label.Value |
| 133 | } |
| 134 | return labels |
| 135 | } |