Add custom attributes for all resource types in vsphere input (#6884)
This commit is contained in:
parent
b908059326
commit
78a7978ea8
|
@ -84,7 +84,7 @@ type metricEntry struct {
|
||||||
fields map[string]interface{}
|
fields map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type objectMap map[string]objectRef
|
type objectMap map[string]*objectRef
|
||||||
|
|
||||||
type objectRef struct {
|
type objectRef struct {
|
||||||
name string
|
name string
|
||||||
|
@ -100,7 +100,7 @@ type objectRef struct {
|
||||||
func (e *Endpoint) getParent(obj *objectRef, res *resourceKind) (*objectRef, bool) {
|
func (e *Endpoint) getParent(obj *objectRef, res *resourceKind) (*objectRef, bool) {
|
||||||
if pKind, ok := e.resourceKinds[res.parent]; ok {
|
if pKind, ok := e.resourceKinds[res.parent]; ok {
|
||||||
if p, ok := pKind.objects[obj.parentRef.Value]; ok {
|
if p, ok := pKind.objects[obj.parentRef.Value]; ok {
|
||||||
return &p, true
|
return p, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -322,7 +322,7 @@ func (e *Endpoint) getMetricNameMap(ctx context.Context) (map[int32]string, erro
|
||||||
return names, nil
|
return names, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Endpoint) getMetadata(ctx context.Context, obj objectRef, sampling int32) (performance.MetricList, error) {
|
func (e *Endpoint) getMetadata(ctx context.Context, obj *objectRef, sampling int32) (performance.MetricList, error) {
|
||||||
client, err := e.clientFactory.GetClient(ctx)
|
client, err := e.clientFactory.GetClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -508,7 +508,7 @@ func (e *Endpoint) simpleMetadataSelect(ctx context.Context, client *Client, res
|
||||||
func (e *Endpoint) complexMetadataSelect(ctx context.Context, res *resourceKind, objects objectMap, metricNames map[int32]string) {
|
func (e *Endpoint) complexMetadataSelect(ctx context.Context, res *resourceKind, objects objectMap, metricNames map[int32]string) {
|
||||||
// We're only going to get metadata from maxMetadataSamples resources. If we have
|
// We're only going to get metadata from maxMetadataSamples resources. If we have
|
||||||
// more resources than that, we pick maxMetadataSamples samples at random.
|
// more resources than that, we pick maxMetadataSamples samples at random.
|
||||||
sampledObjects := make([]objectRef, len(objects))
|
sampledObjects := make([]*objectRef, len(objects))
|
||||||
i := 0
|
i := 0
|
||||||
for _, obj := range objects {
|
for _, obj := range objects {
|
||||||
sampledObjects[i] = obj
|
sampledObjects[i] = obj
|
||||||
|
@ -529,7 +529,7 @@ func (e *Endpoint) complexMetadataSelect(ctx context.Context, res *resourceKind,
|
||||||
instInfoMux := sync.Mutex{}
|
instInfoMux := sync.Mutex{}
|
||||||
te := NewThrottledExecutor(e.Parent.DiscoverConcurrency)
|
te := NewThrottledExecutor(e.Parent.DiscoverConcurrency)
|
||||||
for _, obj := range sampledObjects {
|
for _, obj := range sampledObjects {
|
||||||
func(obj objectRef) {
|
func(obj *objectRef) {
|
||||||
te.Run(ctx, func() {
|
te.Run(ctx, func() {
|
||||||
metrics, err := e.getMetadata(ctx, obj, res.sampling)
|
metrics, err := e.getMetadata(ctx, obj, res.sampling)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -573,8 +573,13 @@ func getDatacenters(ctx context.Context, e *Endpoint, filter *ResourceFilter) (o
|
||||||
}
|
}
|
||||||
m := make(objectMap, len(resources))
|
m := make(objectMap, len(resources))
|
||||||
for _, r := range resources {
|
for _, r := range resources {
|
||||||
m[r.ExtensibleManagedObject.Reference().Value] = objectRef{
|
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
|
||||||
name: r.Name, ref: r.ExtensibleManagedObject.Reference(), parentRef: r.Parent, dcname: r.Name}
|
name: r.Name,
|
||||||
|
ref: r.ExtensibleManagedObject.Reference(),
|
||||||
|
parentRef: r.Parent,
|
||||||
|
dcname: r.Name,
|
||||||
|
customValues: e.loadCustomAttributes(&r.ManagedEntity),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
@ -613,8 +618,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{
|
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
|
||||||
name: r.Name, ref: r.ExtensibleManagedObject.Reference(), parentRef: p}
|
name: r.Name,
|
||||||
|
ref: r.ExtensibleManagedObject.Reference(),
|
||||||
|
parentRef: p,
|
||||||
|
customValues: e.loadCustomAttributes(&r.ManagedEntity),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
@ -627,8 +636,12 @@ func getHosts(ctx context.Context, e *Endpoint, filter *ResourceFilter) (objectM
|
||||||
}
|
}
|
||||||
m := make(objectMap)
|
m := make(objectMap)
|
||||||
for _, r := range resources {
|
for _, r := range resources {
|
||||||
m[r.ExtensibleManagedObject.Reference().Value] = objectRef{
|
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
|
||||||
name: r.Name, ref: r.ExtensibleManagedObject.Reference(), parentRef: r.Parent}
|
name: r.Name,
|
||||||
|
ref: r.ExtensibleManagedObject.Reference(),
|
||||||
|
parentRef: r.Parent,
|
||||||
|
customValues: e.loadCustomAttributes(&r.ManagedEntity),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
@ -693,30 +706,13 @@ func getVMs(ctx context.Context, e *Endpoint, filter *ResourceFilter) (objectMap
|
||||||
guest = cleanGuestID(r.Config.GuestId)
|
guest = cleanGuestID(r.Config.GuestId)
|
||||||
uuid = r.Config.Uuid
|
uuid = r.Config.Uuid
|
||||||
}
|
}
|
||||||
cvs := make(map[string]string)
|
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
|
||||||
if e.customAttrEnabled {
|
|
||||||
for _, cv := range r.Summary.CustomValue {
|
|
||||||
val := cv.(*types.CustomFieldStringValue)
|
|
||||||
if val.Value == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key, ok := e.customFields[val.Key]
|
|
||||||
if !ok {
|
|
||||||
e.Parent.Log.Warnf("Metadata for custom field %d not found. Skipping", val.Key)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e.customAttrFilter.Match(key) {
|
|
||||||
cvs[key] = val.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m[r.ExtensibleManagedObject.Reference().Value] = objectRef{
|
|
||||||
name: r.Name,
|
name: r.Name,
|
||||||
ref: r.ExtensibleManagedObject.Reference(),
|
ref: r.ExtensibleManagedObject.Reference(),
|
||||||
parentRef: r.Runtime.Host,
|
parentRef: r.Runtime.Host,
|
||||||
guest: guest,
|
guest: guest,
|
||||||
altID: uuid,
|
altID: uuid,
|
||||||
customValues: cvs,
|
customValues: e.loadCustomAttributes(&r.ManagedEntity),
|
||||||
lookup: lookup,
|
lookup: lookup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -740,12 +736,40 @@ func getDatastores(ctx context.Context, e *Endpoint, filter *ResourceFilter) (ob
|
||||||
url = info.Url
|
url = info.Url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m[r.ExtensibleManagedObject.Reference().Value] = objectRef{
|
m[r.ExtensibleManagedObject.Reference().Value] = &objectRef{
|
||||||
name: r.Name, ref: r.ExtensibleManagedObject.Reference(), parentRef: r.Parent, altID: url}
|
name: r.Name,
|
||||||
|
ref: r.ExtensibleManagedObject.Reference(),
|
||||||
|
parentRef: r.Parent,
|
||||||
|
altID: url,
|
||||||
|
customValues: e.loadCustomAttributes(&r.ManagedEntity),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Endpoint) loadCustomAttributes(entity *mo.ManagedEntity) map[string]string {
|
||||||
|
if !e.customAttrEnabled {
|
||||||
|
return map[string]string{}
|
||||||
|
}
|
||||||
|
cvs := make(map[string]string)
|
||||||
|
for _, v := range entity.CustomValue {
|
||||||
|
cv, ok := v.(*types.CustomFieldStringValue)
|
||||||
|
if !ok {
|
||||||
|
e.Parent.Log.Warnf("Metadata for custom field %d not of string type. Skipping", cv.Key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key, ok := e.customFields[cv.Key]
|
||||||
|
if !ok {
|
||||||
|
e.Parent.Log.Warnf("Metadata for custom field %d not found. Skipping", cv.Key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if e.customAttrFilter.Match(key) {
|
||||||
|
cvs[key] = cv.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cvs
|
||||||
|
}
|
||||||
|
|
||||||
// Close shuts down an Endpoint and releases any resources associated with it.
|
// Close shuts down an Endpoint and releases any resources associated with it.
|
||||||
func (e *Endpoint) Close() {
|
func (e *Endpoint) Close() {
|
||||||
e.clientFactory.Close()
|
e.clientFactory.Close()
|
||||||
|
@ -1054,7 +1078,7 @@ func (e *Endpoint) collectChunk(ctx context.Context, pqs []types.PerfQuerySpec,
|
||||||
e.Parent.Log.Errorf("MOID %s not found in cache. Skipping", moid)
|
e.Parent.Log.Errorf("MOID %s not found in cache. Skipping", moid)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.populateTags(&objectRef, resourceType, res, t, &v)
|
e.populateTags(objectRef, resourceType, res, t, &v)
|
||||||
|
|
||||||
nValues := 0
|
nValues := 0
|
||||||
alignedInfo, alignedValues := alignSamples(em.SampleInfo, v.Value, interval)
|
alignedInfo, alignedValues := alignSamples(em.SampleInfo, v.Value, interval)
|
||||||
|
|
|
@ -233,12 +233,12 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
addFields = map[string][]string{
|
addFields = map[string][]string{
|
||||||
"HostSystem": {"parent"},
|
"HostSystem": {"parent", "summary.customValue", "customValue"},
|
||||||
"VirtualMachine": {"runtime.host", "config.guestId", "config.uuid", "runtime.powerState",
|
"VirtualMachine": {"runtime.host", "config.guestId", "config.uuid", "runtime.powerState",
|
||||||
"summary.customValue", "guest.net", "guest.hostName"},
|
"summary.customValue", "guest.net", "guest.hostName", "customValue"},
|
||||||
"Datastore": {"parent", "info"},
|
"Datastore": {"parent", "info", "customValue"},
|
||||||
"ClusterComputeResource": {"parent"},
|
"ClusterComputeResource": {"parent", "customValue"},
|
||||||
"Datacenter": {"parent"},
|
"Datacenter": {"parent", "customValue"},
|
||||||
}
|
}
|
||||||
|
|
||||||
containers = map[string]interface{}{
|
containers = map[string]interface{}{
|
||||||
|
|
Loading…
Reference in New Issue