Fix wrong memory measurements of containers and vms (#8290)

This commit is contained in:
tlusser-inv 2020-10-21 16:50:29 +02:00 committed by GitHub
parent 14a73055f4
commit 9c2979dced
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 12 deletions

View File

@ -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"

View File

@ -2,6 +2,7 @@ package proxmox
import (
"encoding/json"
"errors"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"io/ioutil"
@ -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 {
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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),

View File

@ -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("")
@ -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
@ -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
}

View File

@ -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
@ -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"`