Skip to content

Commit

Permalink
Fix wrong memory measurements of containers and vms (influxdata#8290)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlusser-inv authored Oct 21, 2020
1 parent 14a7305 commit 9c2979d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 12 deletions.
2 changes: 2 additions & 0 deletions plugins/inputs/proxmox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Telegraf minimum version: Telegraf 1.16.0
## API connection configuration. The API token was introduced in Proxmox v6.2. Required permissions for user and token: PVEAuditor role on /.
base_url = "https://localhost:8006/api2/json"
api_token = "USER@REALM!TOKENID=UUID"
## Optional node name config
# node_name = "localhost"

## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
Expand Down
48 changes: 39 additions & 9 deletions plugins/inputs/proxmox/proxmox.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package proxmox

import (
"encoding/json"
"errors"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"io/ioutil"
Expand Down Expand Up @@ -48,11 +49,10 @@ func (px *Proxmox) Gather(acc telegraf.Accumulator) error {
}

func (px *Proxmox) Init() error {
hostname, err := os.Hostname()
if err != nil {
return err

if px.NodeName == "" {
return errors.New("node_name must be configured")
}
px.hostname = hostname

tlsCfg, err := px.ClientConfig.TLSConfig()
if err != nil {
Expand All @@ -73,11 +73,15 @@ func init() {
requestFunction: performRequest,
}

// Set hostname as default node name for backwards compatibility
hostname, _ := os.Hostname()
px.NodeName = hostname

inputs.Add("proxmox", func() telegraf.Input { return &px })
}

func getNodeSearchDomain(px *Proxmox) error {
apiUrl := "/nodes/" + px.hostname + "/dns"
apiUrl := "/nodes/" + px.NodeName + "/dns"
jsonData, err := px.requestFunction(px, apiUrl, http.MethodGet, nil)
if err != nil {
return err
Expand All @@ -88,6 +92,10 @@ func getNodeSearchDomain(px *Proxmox) error {
if err != nil {
return err
}

if nodeDns.Data.Searchdomain == "" {
return errors.New("node_name not found")
}
px.nodeSearchDomain = nodeDns.Data.Searchdomain

return nil
Expand Down Expand Up @@ -137,7 +145,12 @@ func gatherVmData(px *Proxmox, acc telegraf.Accumulator, rt ResourceType) {
return
}
tags := getTags(px, vmStat.Name, vmConfig, rt)
fields, err := getFields(vmStat)
currentVMStatus, err := getCurrentVMStatus(px, rt, vmStat.ID)
if err != nil {
px.Log.Error("Error getting VM curent VM status: %v", err)
return
}
fields, err := getFields(currentVMStatus)
if err != nil {
px.Log.Error("Error getting VM measurements: %v", err)
return
Expand All @@ -146,8 +159,25 @@ func gatherVmData(px *Proxmox, acc telegraf.Accumulator, rt ResourceType) {
}
}

func getCurrentVMStatus(px *Proxmox, rt ResourceType, id string) (VmStat, error) {
apiUrl := "/nodes/" + px.NodeName + "/" + string(rt) + "/" + id + "/status/current"

jsonData, err := px.requestFunction(px, apiUrl, http.MethodGet, nil)
if err != nil {
return VmStat{}, err
}

var currentVmStatus VmCurrentStats
err = json.Unmarshal(jsonData, &currentVmStatus)
if err != nil {
return VmStat{}, err
}

return currentVmStatus.Data, nil
}

func getVmStats(px *Proxmox, rt ResourceType) (VmStats, error) {
apiUrl := "/nodes/" + px.hostname + "/" + string(rt)
apiUrl := "/nodes/" + px.NodeName + "/" + string(rt)
jsonData, err := px.requestFunction(px, apiUrl, http.MethodGet, nil)
if err != nil {
return VmStats{}, err
Expand All @@ -163,7 +193,7 @@ func getVmStats(px *Proxmox, rt ResourceType) (VmStats, error) {
}

func getVmConfig(px *Proxmox, vmId string, rt ResourceType) (VmConfig, error) {
apiUrl := "/nodes/" + px.hostname + "/" + string(rt) + "/" + vmId + "/config"
apiUrl := "/nodes/" + px.NodeName + "/" + string(rt) + "/" + vmId + "/config"
jsonData, err := px.requestFunction(px, apiUrl, http.MethodGet, nil)
if err != nil {
return VmConfig{}, err
Expand Down Expand Up @@ -245,7 +275,7 @@ func getTags(px *Proxmox, name string, vmConfig VmConfig, rt ResourceType) map[s
fqdn := hostname + "." + domain

return map[string]string{
"node_fqdn": px.hostname + "." + px.nodeSearchDomain,
"node_fqdn": px.NodeName + "." + px.nodeSearchDomain,
"vm_name": name,
"vm_fqdn": fqdn,
"vm_type": string(rt),
Expand Down
10 changes: 8 additions & 2 deletions plugins/inputs/proxmox/proxmox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ var qemuTestData = `{"data":[{"name":"qemu1","status":"running","maxdisk":107374
var qemuConfigTestData = `{"data":{"hostname":"qemu1","searchdomain":"test.example.com"}}`
var lxcTestData = `{"data":[{"vmid":"111","type":"lxc","uptime":2078164,"swap":9412608,"disk":"744189952","maxmem":536870912,"mem":98500608,"maxswap":536870912,"cpu":0.00371567669193613,"status":"running","maxdisk":"5217320960","name":"container1"}]}`
var lxcConfigTestData = `{"data":{"hostname":"container1","searchdomain":"test.example.com"}}`
var lxcCurrentStatusTestData = `{"data":{"vmid":"111","type":"lxc","uptime":2078164,"swap":9412608,"disk":"744189952","maxmem":536870912,"mem":98500608,"maxswap":536870912,"cpu":0.00371567669193613,"status":"running","maxdisk":"5217320960","name":"container1"}}`
var qemuCurrentStatusTestData = `{"data":{"name":"qemu1","status":"running","maxdisk":10737418240,"cpu":0.029336643550795,"vmid":"113","uptime":2159739,"disk":0,"maxmem":2147483648,"mem":1722451796}}`

func performTestRequest(px *Proxmox, apiUrl string, method string, data url.Values) ([]byte, error) {
var bytedata = []byte("")
Expand All @@ -28,6 +30,10 @@ func performTestRequest(px *Proxmox, apiUrl string, method string, data url.Valu
bytedata = []byte(lxcTestData)
} else if strings.HasSuffix(apiUrl, "111/config") {
bytedata = []byte(lxcConfigTestData)
} else if strings.HasSuffix(apiUrl, "111/status/current") {
bytedata = []byte(lxcCurrentStatusTestData)
} else if strings.HasSuffix(apiUrl, "113/status/current") {
bytedata = []byte(qemuCurrentStatusTestData)
}

return bytedata, nil
Expand All @@ -36,12 +42,12 @@ func performTestRequest(px *Proxmox, apiUrl string, method string, data url.Valu
func setUp(t *testing.T) *Proxmox {
px := &Proxmox{
requestFunction: performTestRequest,
NodeName: "testnode",
}

require.NoError(t, px.Init())

// Override hostname and logger for test
px.hostname = "testnode"
// Override logger for test
px.Log = testutil.Logger{}
return px
}
Expand Down
7 changes: 6 additions & 1 deletion plugins/inputs/proxmox/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ type Proxmox struct {
BaseURL string `toml:"base_url"`
APIToken string `toml:"api_token"`
ResponseTimeout internal.Duration `toml:"response_timeout"`
NodeName string `toml:"node_name"`

tls.ClientConfig

hostname string
httpClient *http.Client
nodeSearchDomain string

Expand All @@ -34,6 +35,10 @@ type VmStats struct {
Data []VmStat `json:"data"`
}

type VmCurrentStats struct {
Data VmStat `json:"data"`
}

type VmStat struct {
ID string `json:"vmid"`
Name string `json:"name"`
Expand Down

0 comments on commit 9c2979d

Please sign in to comment.