vSphere Fixed missing clustername issue 7878 (#8026)

This commit is contained in:
Pontus Rydin 2020-08-26 12:58:28 -04:00 committed by GitHub
parent 48bab9db86
commit 60d402d827
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 25 deletions

View File

@ -348,7 +348,11 @@ func (e *Endpoint) getMetadata(ctx context.Context, obj *objectRef, sampling int
return metrics, nil return metrics, nil
} }
func (e *Endpoint) getDatacenterName(ctx context.Context, client *Client, cache map[string]string, r types.ManagedObjectReference) string { func (e *Endpoint) getDatacenterName(ctx context.Context, client *Client, cache map[string]string, r types.ManagedObjectReference) (string, bool) {
return e.getAncestorName(ctx, client, "Datacenter", cache, r)
}
func (e *Endpoint) getAncestorName(ctx context.Context, client *Client, resourceType string, cache map[string]string, r types.ManagedObjectReference) (string, bool) {
path := make([]string, 0) path := make([]string, 0)
returnVal := "" returnVal := ""
here := r here := r
@ -370,7 +374,7 @@ func (e *Endpoint) getDatacenterName(ctx context.Context, client *Client, cache
e.Parent.Log.Warnf("Error while resolving parent. Assuming no parent exists. Error: %s", err.Error()) e.Parent.Log.Warnf("Error while resolving parent. Assuming no parent exists. Error: %s", err.Error())
return true return true
} }
if result.Reference().Type == "Datacenter" { if result.Reference().Type == resourceType {
// Populate cache for the entire chain of objects leading here. // Populate cache for the entire chain of objects leading here.
returnVal = result.Name returnVal = result.Name
return true return true
@ -386,7 +390,7 @@ func (e *Endpoint) getDatacenterName(ctx context.Context, client *Client, cache
for _, s := range path { for _, s := range path {
cache[s] = returnVal cache[s] = returnVal
} }
return returnVal return returnVal, returnVal != ""
} }
func (e *Endpoint) discover(ctx context.Context) error { func (e *Endpoint) discover(ctx context.Context) error {
@ -436,7 +440,7 @@ func (e *Endpoint) discover(ctx context.Context) error {
if res.name != "Datacenter" { if res.name != "Datacenter" {
for k, obj := range objects { for k, obj := range objects {
if obj.parentRef != nil { if obj.parentRef != nil {
obj.dcname = e.getDatacenterName(ctx, client, dcNameCache, *obj.parentRef) obj.dcname, _ = e.getDatacenterName(ctx, client, dcNameCache, *obj.parentRef)
objects[k] = obj objects[k] = obj
} }
} }
@ -449,11 +453,11 @@ func (e *Endpoint) discover(ctx context.Context) error {
} else { } else {
e.complexMetadataSelect(ctx, res, objects) e.complexMetadataSelect(ctx, res, objects)
} }
newObjects[k] = objects
SendInternalCounterWithTags("discovered_objects", e.URL.Host, map[string]string{"type": res.name}, int64(len(objects)))
numRes += int64(len(objects))
} }
newObjects[k] = objects
SendInternalCounterWithTags("discovered_objects", e.URL.Host, map[string]string{"type": res.name}, int64(len(objects)))
numRes += int64(len(objects))
} }
if err != nil { if err != nil {
e.log.Error(err) e.log.Error(err)
@ -639,6 +643,12 @@ func getClusters(ctx context.Context, e *Endpoint, filter *ResourceFilter) (obje
cache[r.Parent.Value] = p cache[r.Parent.Value] = p
} }
} }
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
name: r.Name,
ref: r.ExtensibleManagedObject.Reference(),
parentRef: p,
customValues: e.loadCustomAttributes(&r.ManagedEntity),
}
return nil return nil
}() }()
if err != nil { if err != nil {

View File

@ -4,7 +4,9 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"os"
"regexp" "regexp"
"strings"
"testing" "testing"
"time" "time"
"unsafe" "unsafe"
@ -150,6 +152,7 @@ func defaultVSphere() *VSphere {
ForceDiscoverOnInit: true, ForceDiscoverOnInit: true,
DiscoverConcurrency: 1, DiscoverConcurrency: 1,
CollectConcurrency: 1, CollectConcurrency: 1,
Separator: ".",
} }
} }
@ -416,9 +419,10 @@ func TestFolders(t *testing.T) {
defer m.Remove() defer m.Remove()
defer s.Close() defer s.Close()
v := defaultVSphere()
ctx := context.Background() ctx := context.Background()
v := defaultVSphere()
c, err := NewClient(ctx, s.URL, v) c, err := NewClient(ctx, s.URL, v)
f := Finder{c} f := Finder{c}
@ -440,27 +444,110 @@ func TestFolders(t *testing.T) {
testLookupVM(ctx, t, &f, "/F0/DC1/vm/**/F*/**", 4, "") testLookupVM(ctx, t, &f, "/F0/DC1/vm/**/F*/**", 4, "")
} }
func TestAll(t *testing.T) { func TestCollection(t *testing.T) {
// Don't run test on 32-bit machines due to bug in simulator. testCollection(t, false)
// https://github.com/vmware/govmomi/issues/1330 }
var i int
if unsafe.Sizeof(i) < 8 {
return
}
m, s, err := createSim(0) func TestCollectionNoClusterMetrics(t *testing.T) {
if err != nil { testCollection(t, true)
t.Fatal(err) }
func testCollection(t *testing.T, excludeClusters bool) {
mustHaveMetrics := map[string]struct{}{
"vsphere.vm.cpu": {},
"vsphere.vm.mem": {},
"vsphere.vm.net": {},
"vsphere.host.cpu": {},
"vsphere.host.mem": {},
"vsphere.host.net": {},
"vsphere.datastore.disk": {},
}
vCenter := os.Getenv("VCENTER_URL")
username := os.Getenv("VCENTER_USER")
password := os.Getenv("VCENTER_PASSWORD")
v := defaultVSphere()
if vCenter != "" {
v.Vcenters = []string{vCenter}
v.Username = username
v.Password = password
} else {
// Don't run test on 32-bit machines due to bug in simulator.
// https://github.com/vmware/govmomi/issues/1330
var i int
if unsafe.Sizeof(i) < 8 {
return
}
m, s, err := createSim(0)
if err != nil {
t.Fatal(err)
}
defer m.Remove()
defer s.Close()
v.Vcenters = []string{s.URL.String()}
}
if excludeClusters {
v.ClusterMetricExclude = []string{"*"}
} }
defer m.Remove()
defer s.Close()
var acc testutil.Accumulator var acc testutil.Accumulator
v := defaultVSphere()
v.Vcenters = []string{s.URL.String()} require.NoError(t, v.Start(&acc))
v.Start(&acc)
defer v.Stop() defer v.Stop()
require.NoError(t, v.Gather(&acc)) require.NoError(t, v.Gather(&acc))
require.Equal(t, 0, len(acc.Errors), fmt.Sprintf("Errors found: %s", acc.Errors)) require.Equal(t, 0, len(acc.Errors), fmt.Sprintf("Errors found: %s", acc.Errors))
require.True(t, len(acc.Metrics) > 0, "No metrics were collected") require.True(t, len(acc.Metrics) > 0, "No metrics were collected")
cache := make(map[string]string)
client, err := v.endpoints[0].clientFactory.GetClient(context.Background())
require.NoError(t, err)
hostCache := make(map[string]string)
for _, m := range acc.Metrics {
delete(mustHaveMetrics, m.Measurement)
if strings.HasPrefix(m.Measurement, "vsphere.vm.") {
mustContainAll(t, m.Tags, []string{"esxhostname", "moid", "vmname", "guest", "dcname", "uuid", "vmname"})
hostName := m.Tags["esxhostname"]
hostMoid, ok := hostCache[hostName]
if !ok {
// We have to follow the host parent path to locate a cluster. Look up the host!
finder := Finder{client}
var hosts []mo.HostSystem
finder.Find(context.Background(), "HostSystem", "/**/"+hostName, &hosts)
require.NotEmpty(t, hosts)
hostMoid = hosts[0].Reference().Value
hostCache[hostName] = hostMoid
}
if isInCluster(t, v, client, cache, "HostSystem", hostMoid) { // If the VM lives in a cluster
mustContainAll(t, m.Tags, []string{"clustername"})
}
} else if strings.HasPrefix(m.Measurement, "vsphere.host.") {
if isInCluster(t, v, client, cache, "HostSystem", m.Tags["moid"]) { // If the host lives in a cluster
mustContainAll(t, m.Tags, []string{"esxhostname", "clustername", "moid", "dcname"})
} else {
mustContainAll(t, m.Tags, []string{"esxhostname", "moid", "dcname"})
}
} else if strings.HasPrefix(m.Measurement, "vsphere.cluster.") {
mustContainAll(t, m.Tags, []string{"clustername", "moid", "dcname"})
} else {
mustContainAll(t, m.Tags, []string{"moid", "dcname"})
}
}
require.Empty(t, mustHaveMetrics, "Some metrics were not found")
}
func isInCluster(t *testing.T, v *VSphere, client *Client, cache map[string]string, resourceKind, moid string) bool {
ctx := context.Background()
ref := types.ManagedObjectReference{
Type: resourceKind,
Value: moid,
}
_, ok := v.endpoints[0].getAncestorName(ctx, client, "ClusterComputeResource", cache, ref)
return ok
}
func mustContainAll(t *testing.T, tagMap map[string]string, mustHave []string) {
for _, tag := range mustHave {
require.Contains(t, tagMap, tag)
}
} }

View File

@ -199,7 +199,7 @@ func (w *Wavefront) buildMetrics(m telegraf.Metric) []*MetricPoint {
metricValue, buildError := buildValue(value, metric.Metric, w) metricValue, buildError := buildValue(value, metric.Metric, w)
if buildError != nil { if buildError != nil {
w.Log.Debug("Error building tags: %s\n", buildError.Error()) w.Log.Debugf("Error building tags: %s\n", buildError.Error())
continue continue
} }
metric.Value = metricValue metric.Value = metricValue