Skip to content

Commit

Permalink
Fix nil pointers accesses causing panics in Metricbeat Vsphere module (
Browse files Browse the repository at this point in the history
…#9784) (#9822)

In Vsphere module, some fields returned by the Vsphere library contain pointers to some values that could potentially be nil. With this PR, we do a nil-check prior every access to any of those fields to avoid their writing in case they are nil and protecting Metricbeat from panicking.

(cherry picked from commit 7c31ced)
  • Loading branch information
sayden authored Dec 31, 2018
1 parent bad60fe commit 55bf40e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 59 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ https://github.com/elastic/beats/compare/v6.6.0...6.x[Check the HEAD diff]
- Add missing journalbeat non breaking fixes. {pull}9106[9106]

*Metricbeat*
- Fix panics in vsphere module when certain values where not returned by the API. {pull}9784[9784]

- Add missing namespace field in http server metricset {pull}7890[7890]
- Fix race condition when enriching events with kubernetes metadata. {issue}9055[9055] {issue}9067[9067]
Expand Down
47 changes: 18 additions & 29 deletions metricbeat/module/vsphere/host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import (
"github.com/vmware/govmomi/vim25/types"
)

var logger = logp.NewLogger("vsphere")

func init() {
mb.Registry.MustAddMetricSet("vsphere", "host", New,
mb.DefaultMetricSet(),
Expand Down Expand Up @@ -111,40 +113,27 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) {
}

for _, hs := range hst {
totalCPU := int64(hs.Summary.Hardware.CpuMhz) * int64(hs.Summary.Hardware.NumCpuCores)
freeCPU := int64(totalCPU) - int64(hs.Summary.QuickStats.OverallCpuUsage)
freeMemory := int64(hs.Summary.Hardware.MemorySize) - (int64(hs.Summary.QuickStats.OverallMemoryUsage) * 1024 * 1024)

event := common.MapStr{
"name": hs.Summary.Config.Name,
"cpu": common.MapStr{
"used": common.MapStr{
"mhz": hs.Summary.QuickStats.OverallCpuUsage,
},
"total": common.MapStr{
"mhz": totalCPU,
},
"free": common.MapStr{
"mhz": freeCPU,
},
},
"memory": common.MapStr{
"used": common.MapStr{
"bytes": (int64(hs.Summary.QuickStats.OverallMemoryUsage) * 1024 * 1024),
},
"total": common.MapStr{
"bytes": hs.Summary.Hardware.MemorySize,
},
"free": common.MapStr{
"bytes": freeMemory,
},
},

event := common.MapStr{}

event["name"] = hs.Summary.Config.Name
event.Put("cpu.used.mhz", hs.Summary.QuickStats.OverallCpuUsage)
event.Put("memory.used.bytes", int64(hs.Summary.QuickStats.OverallMemoryUsage)*1024*1024)

if hs.Summary.Hardware != nil {
totalCPU := int64(hs.Summary.Hardware.CpuMhz) * int64(hs.Summary.Hardware.NumCpuCores)
event.Put("cpu.total.mhz", totalCPU)
event.Put("cpu.free.mhz", int64(totalCPU)-int64(hs.Summary.QuickStats.OverallCpuUsage))
event.Put("memory.free.bytes", int64(hs.Summary.Hardware.MemorySize)-(int64(hs.Summary.QuickStats.OverallMemoryUsage)*1024*1024))
event.Put("memory.total.bytes", hs.Summary.Hardware.MemorySize)
} else {
logger.Debug("'Hardware' or 'Summary' data not found. This is either a parsing error from vsphere library, an error trying to reach host/guest or incomplete information returned from host/guest")
}

if hs.Summary.Host != nil {
networkNames, err := getNetworkNames(ctx, c, hs.Summary.Host.Reference())
if err != nil {
logp.Debug("vsphere", err.Error())
logger.Debugf("error trying to get network names: %s", err.Error())
} else {
if len(networkNames) > 0 {
event["network_names"] = networkNames
Expand Down
53 changes: 23 additions & 30 deletions metricbeat/module/vsphere/virtualmachine/virtualmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
"github.com/vmware/govmomi/vim25/types"
)

var logger = logp.NewLogger("vsphere")

func init() {
mb.Registry.MustAddMetricSet("vsphere", "virtualmachine", New,
mb.DefaultMetricSet(),
Expand Down Expand Up @@ -138,49 +140,40 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) {

freeMemory := (int64(vm.Summary.Config.MemorySizeMB) * 1024 * 1024) - (int64(vm.Summary.QuickStats.GuestMemoryUsage) * 1024 * 1024)

event := common.MapStr{
"host": vm.Summary.Runtime.Host.Value,
"name": vm.Summary.Config.Name,
"cpu": common.MapStr{
"used": common.MapStr{
"mhz": vm.Summary.QuickStats.OverallCpuUsage,
},
},
"memory": common.MapStr{
"used": common.MapStr{
"guest": common.MapStr{
"bytes": (int64(vm.Summary.QuickStats.GuestMemoryUsage) * 1024 * 1024),
},
"host": common.MapStr{
"bytes": (int64(vm.Summary.QuickStats.HostMemoryUsage) * 1024 * 1024),
},
},
"total": common.MapStr{
"guest": common.MapStr{
"bytes": (int64(vm.Summary.Config.MemorySizeMB) * 1024 * 1024),
},
},
"free": common.MapStr{
"guest": common.MapStr{
"bytes": freeMemory,
},
},
},
event := common.MapStr{}

event["name"] = vm.Summary.Config.Name
event.Put("cpu.used.mhz", vm.Summary.QuickStats.OverallCpuUsage)
event.Put("memory.used.guest.bytes", int64(vm.Summary.QuickStats.GuestMemoryUsage)*1024*1024)
event.Put("memory.used.host.bytes", int64(vm.Summary.QuickStats.HostMemoryUsage)*1024*1024)
event.Put("memory.total.guest.bytes", int64(vm.Summary.Config.MemorySizeMB)*1024*1024)
event.Put("memory.free.guest.bytes", freeMemory)

if vm.Summary.Runtime.Host != nil {
event["host"] = vm.Summary.Runtime.Host.Value
} else {
logger.Debug("'Host', 'Runtime' or 'Summary' data not found. This is either a parsing error " +
"from vsphere library, an error trying to reach host/guest or incomplete information returned " +
"from host/guest")
}

// Get custom fields (attributes) values if get_custom_fields is true.
if m.GetCustomFields {
if m.GetCustomFields && vm.Summary.CustomValue != nil {
customFields := getCustomFields(vm.Summary.CustomValue, customFieldsMap)

if len(customFields) > 0 {
event["custom_fields"] = customFields
}
} else {
logger.Debug("custom fields not activated or custom values not found/parse in Summary data. This " +
"is either a parsing error from vsphere library, an error trying to reach host/guest or incomplete " +
"information returned from host/guest")
}

if vm.Summary.Vm != nil {
networkNames, err := getNetworkNames(c, vm.Summary.Vm.Reference())
if err != nil {
logp.Debug("vsphere", err.Error())
logger.Debug(err.Error())
} else {
if len(networkNames) > 0 {
event["network_names"] = networkNames
Expand Down

0 comments on commit 55bf40e

Please sign in to comment.