github.com/vmware/govmomi@v0.51.0/simulator/performance_manager_test.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package simulator 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "strings" 12 "testing" 13 14 "github.com/vmware/govmomi/performance" 15 "github.com/vmware/govmomi/simulator/esx" 16 "github.com/vmware/govmomi/simulator/vpx" 17 "github.com/vmware/govmomi/vim25/mo" 18 "github.com/vmware/govmomi/vim25/types" 19 ) 20 21 func testMetricsConsistency(counterInfo []types.PerfCounterInfo, ids [][]types.PerfMetricId) error { 22 23 // Build a lookup table for speed and convenience 24 lookup := make(map[int32]bool, len(counterInfo)) 25 for _, pc := range counterInfo { 26 lookup[pc.Key] = true 27 } 28 29 // Check metric ids against map 30 for _, list := range ids { 31 for _, id := range list { 32 if _, ok := lookup[id.CounterId]; !ok { 33 return fmt.Errorf("Counter with ID %d not found in PerfCounter", id.CounterId) 34 } 35 } 36 } 37 return nil 38 } 39 40 func TestMetricsConsistency(t *testing.T) { 41 esxIds := [][]types.PerfMetricId{esx.VmMetrics, esx.HostMetrics, esx.ResourcePoolMetrics} 42 vpxIds := [][]types.PerfMetricId{vpx.VmMetrics, vpx.HostMetrics, vpx.ClusterMetrics, 43 vpx.DatastoreMetrics, vpx.ResourcePoolMetrics} 44 if err := testMetricsConsistency(esx.PerfCounter, esxIds); err != nil { 45 t.Fatal(err) 46 } 47 if err := testMetricsConsistency(vpx.PerfCounter, vpxIds); err != nil { 48 t.Fatal(err) 49 } 50 } 51 52 func checkDuplicates(ids []types.PerfMetricId) error { 53 m := make(map[string]bool, len(ids)) 54 for _, id := range ids { 55 k := fmt.Sprintf("%d|%s", id.CounterId, id.Instance) 56 if _, ok := m[k]; ok { 57 return fmt.Errorf("Duplicate metric key: %s", k) 58 } 59 m[k] = true 60 } 61 return nil 62 } 63 64 func TestMetricsDuplicates(t *testing.T) { 65 if err := checkDuplicates(esx.VmMetrics); err != nil { 66 t.Fatal(err) 67 } 68 if err := checkDuplicates(esx.HostMetrics); err != nil { 69 t.Fatal(err) 70 } 71 if err := checkDuplicates(vpx.VmMetrics); err != nil { 72 t.Fatal(err) 73 } 74 if err := checkDuplicates(vpx.HostMetrics); err != nil { 75 t.Fatal(err) 76 } 77 if err := checkDuplicates(vpx.ClusterMetrics); err != nil { 78 t.Fatal(err) 79 } 80 if err := checkDuplicates(vpx.DatastoreMetrics); err != nil { 81 t.Fatal(err) 82 } 83 } 84 85 func TestQueryProviderSummary(t *testing.T) { 86 m := VPX() 87 88 err := m.Create() 89 if err != nil { 90 t.Fatal(err) 91 } 92 93 defer m.Remove() 94 95 c := m.Service.client() 96 97 p := performance.NewManager(c) 98 ctx := m.Service.Context 99 100 vm := ctx.Map.Any("VirtualMachine").(*VirtualMachine) 101 if info, err := p.ProviderSummary(ctx, vm.Reference()); err != nil { 102 t.Fatal(err) 103 } else { 104 if info.RefreshRate != 20 { 105 t.Fatalf("VM wefresh rate is %d, should be 20", info.RefreshRate) 106 } 107 } 108 109 host := ctx.Map.Any("HostSystem").(*HostSystem) 110 if info, err := p.ProviderSummary(ctx, host.Reference()); err != nil { 111 t.Fatal(err) 112 } else { 113 if info.RefreshRate != 20 { 114 t.Fatalf("Host refresh rate is %d, should be 20", info.RefreshRate) 115 } 116 } 117 118 pool := ctx.Map.Any("ResourcePool").(*ResourcePool) 119 if info, err := p.ProviderSummary(ctx, pool.Reference()); err != nil { 120 t.Fatal(err) 121 } else { 122 if info.RefreshRate != 20 { 123 t.Fatalf("ResourcePool refresh rate is %d, should be 20", info.RefreshRate) 124 } 125 } 126 127 cluster := ctx.Map.Any("ClusterComputeResource").(*ClusterComputeResource) 128 if info, err := p.ProviderSummary(ctx, cluster.Reference()); err != nil { 129 t.Fatal(err) 130 } else { 131 if info.RefreshRate != -1 { 132 t.Fatalf("Cluster refresh rate is %d, should be -1", info.RefreshRate) 133 } 134 } 135 136 datastore := ctx.Map.Any("Datastore").(*Datastore) 137 if info, err := p.ProviderSummary(ctx, datastore.Reference()); err != nil { 138 t.Fatal(err) 139 } else { 140 if info.RefreshRate != -1 { 141 t.Fatalf("Datastore refresh rate is %d, should be -1", info.RefreshRate) 142 } 143 } 144 145 nonExistent := types.ManagedObjectReference{ 146 Type: "Not a valid type", 147 Value: "This object doesn't exist", 148 } 149 if _, err := p.ProviderSummary(ctx, nonExistent); err == nil { 150 t.Fatal("This should have failed (nonexistent object)") 151 } 152 } 153 154 func TestQueryAvailablePerfMetric(t *testing.T) { 155 m := VPX() 156 157 err := m.Create() 158 if err != nil { 159 t.Fatal(err) 160 } 161 162 defer m.Remove() 163 164 c := m.Service.client() 165 p := performance.NewManager(c) 166 ctx := m.Service.Context 167 168 vm := ctx.Map.Any("VirtualMachine").(*VirtualMachine) 169 if info, err := p.AvailableMetric(ctx, vm.Reference(), 20); err != nil { 170 t.Fatal(err) 171 } else { 172 if len(info) == 0 { 173 t.Fatal("Expected non-empty list of vm") 174 } 175 } 176 177 host := ctx.Map.Any("HostSystem").(*HostSystem) 178 if info, err := p.AvailableMetric(ctx, host.Reference(), 20); err != nil { 179 t.Fatal(err) 180 } else { 181 if len(info) == 0 { 182 t.Fatal("Expected non-empty list of host") 183 } 184 var ids []int32 185 for i := range info { 186 ids = append(ids, info[i].CounterId) 187 } 188 perf, err := p.QueryCounter(ctx, ids) 189 if err != nil { 190 t.Fatal(err) 191 } 192 if len(perf) != len(ids) { 193 t.Errorf("%d counters", len(perf)) 194 } 195 } 196 197 pool := ctx.Map.Any("ResourcePool").(*ResourcePool) 198 if info, err := p.AvailableMetric(ctx, pool.Reference(), 20); err != nil { 199 t.Fatal(err) 200 } else { 201 if len(info) == 0 { 202 t.Fatal("Expected non-empty list of resource pool") 203 } 204 } 205 206 cluster := ctx.Map.Any("ClusterComputeResource").(*ClusterComputeResource) 207 if info, err := p.AvailableMetric(ctx, cluster.Reference(), 300); err != nil { 208 t.Fatal(err) 209 } else { 210 if len(info) == 0 { 211 t.Fatal("Expected non-empty list of clusters") 212 } 213 } 214 215 if info, err := p.AvailableMetric(ctx, cluster.Reference(), 20); err != nil { 216 t.Fatal(err) 217 } else { 218 if len(info) != 0 { 219 t.Fatal("Expected empty list of clusters") 220 } 221 } 222 223 ds := ctx.Map.Any("Datastore").(*Datastore) 224 if info, err := p.AvailableMetric(ctx, ds.Reference(), 300); err != nil { 225 t.Fatal(err) 226 } else { 227 if len(info) == 0 { 228 t.Fatal("Expected non-empty list of datastores") 229 } 230 } 231 232 if info, err := p.AvailableMetric(ctx, ds.Reference(), 20); err != nil { 233 t.Fatal(err) 234 } else { 235 if len(info) != 0 { 236 t.Fatal("Expected empty list of datastores") 237 } 238 } 239 240 dc := ctx.Map.Any("Datacenter").(*Datacenter) 241 if info, err := p.AvailableMetric(ctx, dc.Reference(), 300); err != nil { 242 t.Fatal(err) 243 } else { 244 if len(info) == 0 { 245 t.Fatal("Expected non-empty list of datacenters") 246 } 247 } 248 249 if info, err := p.AvailableMetric(ctx, dc.Reference(), 20); err != nil { 250 t.Fatal(err) 251 } else { 252 if len(info) != 0 { 253 t.Fatal("Expected empty list of datacenters") 254 } 255 } 256 257 } 258 259 func testPerfQuery(ctx context.Context, m *Model, e mo.Entity, interval int32, maxSample int32) error { 260 c := m.Service.client() 261 262 p := performance.NewManager(c) 263 264 // Single metric, single VM 265 // 266 qs := []types.PerfQuerySpec{ 267 { 268 MaxSample: maxSample, 269 IntervalId: interval, 270 MetricId: []types.PerfMetricId{{CounterId: 1, Instance: ""}}, 271 Entity: e.Reference(), 272 }, 273 } 274 result, err := p.Query(ctx, qs) 275 if err != nil { 276 return err 277 } 278 if len(result) == 0 { 279 return errors.New("Empty result set") 280 } 281 ms, err := p.ToMetricSeries(ctx, result) 282 if err != nil { 283 return err 284 } 285 if len(ms) == 0 { 286 return errors.New("Empty metric series") 287 } 288 for _, em := range ms { 289 if len(em.SampleInfo) == 0 { 290 return errors.New("Empty SampleInfo") 291 } 292 } 293 294 return nil 295 } 296 297 func testPerfQueryCSV(ctx context.Context, m *Model, e mo.Entity, interval int32, maxSample int32) error { 298 c := m.Service.client() 299 300 p := performance.NewManager(c) 301 302 // Single metric, single VM 303 // 304 qs := []types.PerfQuerySpec{ 305 { 306 MaxSample: maxSample, 307 IntervalId: interval, 308 MetricId: []types.PerfMetricId{{CounterId: 1, Instance: ""}}, 309 Entity: e.Reference(), 310 Format: string(types.PerfFormatCsv), 311 }, 312 } 313 series, err := p.Query(ctx, qs) 314 if err != nil { 315 return err 316 } 317 if len(series) == 0 { 318 return errors.New("Empty result set") 319 } 320 for i := range series { 321 s, ok := series[i].(*types.PerfEntityMetricCSV) 322 if !ok { 323 panic(fmt.Errorf("expected type %T, got: %T", s, series[i])) 324 } 325 if len(s.SampleInfoCSV) == 0 { 326 return errors.New("Empty SampleInfoCSV") 327 } 328 if len(strings.Split(s.SampleInfoCSV, ",")) == 0 { 329 return errors.New("SampleInfoCSV not in CSV format") 330 } 331 for _, v := range s.Value { 332 if len(v.Value) == 0 { 333 return errors.New("Empty PerfEntityMetricCSV.Value") 334 } 335 if len(strings.Split(v.Value, ",")) == 0 { 336 return errors.New("PerfEntityMetricCSV.Value not in CSV format") 337 } 338 } 339 } 340 341 return nil 342 } 343 344 func TestQueryPerf(t *testing.T) { 345 m := VPX() 346 347 err := m.Create() 348 if err != nil { 349 t.Fatal(err) 350 } 351 352 defer m.Remove() 353 354 ctx := m.Service.Context 355 356 for _, maxSample := range []int32{4, 0} { 357 if err := testPerfQuery(ctx, m, ctx.Map.Any("VirtualMachine"), 20, maxSample); err != nil { 358 t.Fatal(err) 359 } 360 if err := testPerfQuery(ctx, m, ctx.Map.Any("HostSystem"), 20, maxSample); err != nil { 361 t.Fatal(err) 362 } 363 if err := testPerfQuery(ctx, m, ctx.Map.Any("ClusterComputeResource"), 300, maxSample); err != nil { 364 t.Fatal(err) 365 } 366 if err := testPerfQuery(ctx, m, ctx.Map.Any("Datastore"), 300, maxSample); err != nil { 367 t.Fatal(err) 368 } 369 if err := testPerfQuery(ctx, m, ctx.Map.Any("Datacenter"), 300, maxSample); err != nil { 370 t.Fatal(err) 371 } 372 if err := testPerfQuery(ctx, m, ctx.Map.Any("ResourcePool"), 300, maxSample); err != nil { 373 t.Fatal(err) 374 } 375 376 //csv format 377 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("VirtualMachine"), 20, maxSample); err != nil { 378 t.Fatal(err) 379 } 380 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("HostSystem"), 20, maxSample); err != nil { 381 t.Fatal(err) 382 } 383 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("ClusterComputeResource"), 300, maxSample); err != nil { 384 t.Fatal(err) 385 } 386 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("Datastore"), 300, maxSample); err != nil { 387 t.Fatal(err) 388 } 389 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("Datacenter"), 300, maxSample); err != nil { 390 t.Fatal(err) 391 } 392 if err := testPerfQueryCSV(ctx, m, ctx.Map.Any("ResourcePool"), 300, maxSample); err != nil { 393 t.Fatal(err) 394 } 395 } 396 }