Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
128
plugins/inputs/xtremio/README.md
Normal file
128
plugins/inputs/xtremio/README.md
Normal file
|
@ -0,0 +1,128 @@
|
|||
# XtremIO Input Plugin
|
||||
|
||||
The `xtremio` plugin gathers metrics from a Dell EMC XtremIO Storage Array's V3
|
||||
Rest API. Documentation can be found [here][1].
|
||||
|
||||
[1]: https://dl.dell.com/content/docu96624_xtremio-storage-array-x1-and-x2-cluster-types-with-xms-6-3-0-to-6-3-3-and-xios-4-0-15-to-4-0-31-and-6-0-0-to-6-3-3-restful-api-3-x-guide.pdf?language=en_us
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Gathers Metrics From a Dell EMC XtremIO Storage Array's V3 API
|
||||
[[inputs.xtremio]]
|
||||
## XtremIO User Interface Endpoint
|
||||
url = "https://xtremio.example.com/" # required
|
||||
|
||||
## Credentials
|
||||
username = "user1"
|
||||
password = "pass123"
|
||||
|
||||
## Metrics to collect from the XtremIO
|
||||
# collectors = ["bbus","clusters","ssds","volumes","xms"]
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use SSL but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
- bbus
|
||||
- tags:
|
||||
- serial_number
|
||||
- guid
|
||||
- power_feed
|
||||
- name
|
||||
- model_name
|
||||
- fields:
|
||||
- bbus_power
|
||||
- bbus_average_daily_temp
|
||||
- bbus_enabled
|
||||
- bbus_ups_need_battery_replacement
|
||||
- bbus_ups_low_battery_no_input
|
||||
|
||||
- clusters
|
||||
- tags:
|
||||
- hardware_platform
|
||||
- license_id
|
||||
- guid
|
||||
- name
|
||||
- sys_psnt_serial_number
|
||||
- fields:
|
||||
- clusters_compression_factor
|
||||
- clusters_percent_memory_in_use
|
||||
- clusters_read_iops
|
||||
- clusters_write_iops
|
||||
- clusters_number_of_volumes
|
||||
- clusters_free_ssd_space_in_percent
|
||||
- clusters_ssd_num
|
||||
- clusters_data_reduction_ratio
|
||||
|
||||
- ssds
|
||||
- tags:
|
||||
- model_name
|
||||
- firmware_version
|
||||
- ssd_uid
|
||||
- guid
|
||||
- sys_name
|
||||
- serial_number
|
||||
- fields:
|
||||
- ssds_ssd_size
|
||||
- ssds_ssd_space_in_use
|
||||
- ssds_write_iops
|
||||
- ssds_read_iops
|
||||
- ssds_write_bandwidth
|
||||
- ssds_read_bandwidth
|
||||
- ssds_num_bad_sectors
|
||||
|
||||
- volumes
|
||||
- tags:
|
||||
- guid
|
||||
- sys_name
|
||||
- name
|
||||
- fields:
|
||||
- volumes_read_iops
|
||||
- volumes_write_iops
|
||||
- volumes_read_latency
|
||||
- volumes_write_latency
|
||||
- volumes_data_reduction_ratio
|
||||
- volumes_provisioned_space
|
||||
- volumes_used_space
|
||||
|
||||
- xms
|
||||
- tags:
|
||||
- guid
|
||||
- name
|
||||
- version
|
||||
- xms_ip
|
||||
- fields:
|
||||
- xms_write_iops
|
||||
- xms_read_iops
|
||||
- xms_overall_efficiency_ratio
|
||||
- xms_ssd_space_in_use
|
||||
- xms_ram_in_use
|
||||
- xms_ram_total
|
||||
- xms_cpu_usage_total
|
||||
- xms_write_latency
|
||||
- xms_read_latency
|
||||
- xms_user_accounts_count
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
xio,guid=abcdefghifklmnopqrstuvwxyz111111,host=HOSTNAME,model_name=Eaton\ 5P\ 1550,name=X2-BBU,power_feed=PWR-B,serial_number=SER1234567890 bbus_average_daily_temp=22i,bbus_enabled=1i,bbus_power=286i,bbus_ups_low_battery_no_input=0i,bbus_ups_need_battery_replacement=0i 1638295340000000000
|
||||
xio,guid=abcdefghifklmnopqrstuvwxyz222222,host=HOSTNAME,model_name=Eaton\ 5P\ 1550,name=X1-BBU,power_feed=PWR-A,serial_number=SER1234567891 bbus_average_daily_temp=22i,bbus_enabled=1i,bbus_power=246i,bbus_ups_low_battery_no_input=0i,bbus_ups_need_battery_replacement=0i 1638295340000000000
|
||||
xio,guid=abcdefghifklmnopqrstuvwxyz333333,hardware_platform=X1,host=HOSTNAME,license_id=LIC123456789,name=SERVER01,sys_psnt_serial_number=FNM01234567890 clusters_compression_factor=1.5160012465000001,clusters_data_reduction_ratio=2.1613617899,clusters_free_ssd_space_in_percent=34i,clusters_number_of_volumes=36i,clusters_percent_memory_in_use=29i,clusters_read_iops=331i,clusters_ssd_num=50i,clusters_write_iops=4649i 1638295341000000000
|
||||
```
|
18
plugins/inputs/xtremio/sample.conf
Normal file
18
plugins/inputs/xtremio/sample.conf
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Gathers Metrics From a Dell EMC XtremIO Storage Array's V3 API
|
||||
[[inputs.xtremio]]
|
||||
## XtremIO User Interface Endpoint
|
||||
url = "https://xtremio.example.com/" # required
|
||||
|
||||
## Credentials
|
||||
username = "user1"
|
||||
password = "pass123"
|
||||
|
||||
## Metrics to collect from the XtremIO
|
||||
# collectors = ["bbus","clusters","ssds","volumes","xms"]
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use SSL but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
20
plugins/inputs/xtremio/testdata/sample_bbu_response.json
vendored
Normal file
20
plugins/inputs/xtremio/testdata/sample_bbu_response.json
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"content": {
|
||||
"is-low-battery-has-input": "false",
|
||||
"serial-number": "A123B45678",
|
||||
"guid": "987654321abcdef",
|
||||
"brick-name": "X1",
|
||||
"ups-battery-charge-in-percent": 100,
|
||||
"power": 244,
|
||||
"avg-daily-temp": 23,
|
||||
"fw-version": "01.02.0034",
|
||||
"sys-name": "ABCXIO001",
|
||||
"power-feed": "PWR-A",
|
||||
"ups-load-in-percent": 21,
|
||||
"name": "X1-BBU",
|
||||
"enabled-state": "enabled",
|
||||
"is-low-battery-no-input": "false",
|
||||
"ups-need-battery-replacement": "false",
|
||||
"model-name": "Eaton Model Name"
|
||||
}
|
||||
}
|
15
plugins/inputs/xtremio/testdata/sample_get_bbu_response.json
vendored
Normal file
15
plugins/inputs/xtremio/testdata/sample_get_bbu_response.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"bbus": [
|
||||
{
|
||||
"href": "https://127.0.0.1/api/json/v3/types/bbus/987654321abcdef",
|
||||
"name": "X1-BBU",
|
||||
"sys-name": "ABCXIO001"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://127.0.0.1/api/json/v3/types/bbus/",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
382
plugins/inputs/xtremio/xtremio.go
Normal file
382
plugins/inputs/xtremio/xtremio.go
Normal file
|
@ -0,0 +1,382 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package xtremio
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal/choice"
|
||||
"github.com/influxdata/telegraf/plugins/common/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type XtremIO struct {
|
||||
Username string `toml:"username"`
|
||||
Password string `toml:"password"`
|
||||
URL string `toml:"url"`
|
||||
Collectors []string `toml:"collectors"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
tls.ClientConfig
|
||||
|
||||
cookie *http.Cookie
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func (*XtremIO) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (xio *XtremIO) Init() error {
|
||||
if xio.Username == "" {
|
||||
return errors.New("username cannot be empty")
|
||||
}
|
||||
if xio.Password == "" {
|
||||
return errors.New("password cannot be empty")
|
||||
}
|
||||
if xio.URL == "" {
|
||||
return errors.New("url cannot be empty")
|
||||
}
|
||||
|
||||
availableCollectors := []string{"bbus", "clusters", "ssds", "volumes", "xms"}
|
||||
if len(xio.Collectors) == 0 {
|
||||
xio.Collectors = availableCollectors
|
||||
}
|
||||
|
||||
for _, collector := range xio.Collectors {
|
||||
if !choice.Contains(collector, availableCollectors) {
|
||||
return fmt.Errorf("specified collector %q isn't supported", collector)
|
||||
}
|
||||
}
|
||||
|
||||
tlsCfg, err := xio.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
xio.client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsCfg,
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (xio *XtremIO) Gather(acc telegraf.Accumulator) error {
|
||||
if err := xio.authenticate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if xio.cookie == nil {
|
||||
return errors.New("no authentication cookie set")
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, collector := range xio.Collectors {
|
||||
wg.Add(1)
|
||||
go func(collector string) {
|
||||
defer wg.Done()
|
||||
|
||||
resp, err := xio.call(collector)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := collectorResponse{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
}
|
||||
|
||||
var arr []href
|
||||
switch collector {
|
||||
case "bbus":
|
||||
arr = data.BBUs
|
||||
case "clusters":
|
||||
arr = data.Clusters
|
||||
case "ssds":
|
||||
arr = data.SSDs
|
||||
case "volumes":
|
||||
arr = data.Volumes
|
||||
case "xms":
|
||||
arr = data.XMS
|
||||
}
|
||||
|
||||
for _, item := range arr {
|
||||
itemSplit := strings.Split(item.Href, "/")
|
||||
if len(itemSplit) < 1 {
|
||||
continue
|
||||
}
|
||||
url := collector + "/" + itemSplit[len(itemSplit)-1]
|
||||
|
||||
// Each collector is ran in a goroutine so they can be run in parallel.
|
||||
// Each collector does an initial query to build out the subqueries it
|
||||
// needs to run, which are started here in nested goroutines. A future
|
||||
// refactor opportunity would be for the initial collector goroutines to
|
||||
// return the results while exiting the goroutine, and then a series of
|
||||
// goroutines can be kicked off for the subqueries. That way there is no
|
||||
// nesting of goroutines.
|
||||
switch collector {
|
||||
case "bbus":
|
||||
wg.Add(1)
|
||||
go xio.gatherBBUs(acc, url, &wg)
|
||||
case "clusters":
|
||||
wg.Add(1)
|
||||
go xio.gatherClusters(acc, url, &wg)
|
||||
case "ssds":
|
||||
wg.Add(1)
|
||||
go xio.gatherSSDs(acc, url, &wg)
|
||||
case "volumes":
|
||||
wg.Add(1)
|
||||
go xio.gatherVolumes(acc, url, &wg)
|
||||
case "xms":
|
||||
wg.Add(1)
|
||||
go xio.gatherXMS(acc, url, &wg)
|
||||
default:
|
||||
acc.AddError(fmt.Errorf("specified collector %q isn't supported", collector))
|
||||
}
|
||||
}
|
||||
}(collector)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// At the beginning of every collection, we re-authenticate.
|
||||
// We reset this cookie so we don't accidentally use an
|
||||
// expired cookie, we can just check if it's nil and know
|
||||
// that we either need to re-authenticate or that the
|
||||
// authentication failed to set the cookie.
|
||||
xio.cookie = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (xio *XtremIO) gatherBBUs(acc telegraf.Accumulator, url string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
resp, err := xio.call(url)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := bbu{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"serial_number": data.Content.Serial,
|
||||
"guid": data.Content.GUID,
|
||||
"power_feed": data.Content.PowerFeed,
|
||||
"name": data.Content.Name,
|
||||
"model_name": data.Content.ModelName,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"bbus_power": data.Content.BBUPower,
|
||||
"bbus_average_daily_temp": data.Content.BBUDailyTemp,
|
||||
"bbus_enabled": (data.Content.BBUEnabled == "enabled"),
|
||||
"bbus_ups_need_battery_replacement": data.Content.BBUNeedBat,
|
||||
"bbus_ups_low_battery_no_input": data.Content.BBULowBat,
|
||||
}
|
||||
|
||||
acc.AddFields("xio", fields, tags)
|
||||
}
|
||||
|
||||
func (xio *XtremIO) gatherClusters(acc telegraf.Accumulator, url string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
resp, err := xio.call(url)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := clusters{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"hardware_platform": data.Content.HardwarePlatform,
|
||||
"license_id": data.Content.LicenseID,
|
||||
"guid": data.Content.GUID,
|
||||
"name": data.Content.Name,
|
||||
"sys_psnt_serial_number": data.Content.SerialNumber,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"clusters_compression_factor": data.Content.CompressionFactor,
|
||||
"clusters_percent_memory_in_use": data.Content.MemoryUsed,
|
||||
"clusters_read_iops": data.Content.ReadIops,
|
||||
"clusters_write_iops": data.Content.WriteIops,
|
||||
"clusters_number_of_volumes": data.Content.NumVolumes,
|
||||
"clusters_free_ssd_space_in_percent": data.Content.FreeSSDSpace,
|
||||
"clusters_ssd_num": data.Content.NumSSDs,
|
||||
"clusters_data_reduction_ratio": data.Content.DataReductionRatio,
|
||||
}
|
||||
|
||||
acc.AddFields("xio", fields, tags)
|
||||
}
|
||||
|
||||
func (xio *XtremIO) gatherSSDs(acc telegraf.Accumulator, url string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
resp, err := xio.call(url)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := ssd{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"model_name": data.Content.ModelName,
|
||||
"firmware_version": data.Content.FirmwareVersion,
|
||||
"ssd_uid": data.Content.SSDuid,
|
||||
"guid": data.Content.GUID,
|
||||
"sys_name": data.Content.SysName,
|
||||
"serial_number": data.Content.SerialNumber,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"ssds_ssd_size": data.Content.Size,
|
||||
"ssds_ssd_space_in_use": data.Content.SpaceUsed,
|
||||
"ssds_write_iops": data.Content.WriteIops,
|
||||
"ssds_read_iops": data.Content.ReadIops,
|
||||
"ssds_write_bandwidth": data.Content.WriteBandwidth,
|
||||
"ssds_read_bandwidth": data.Content.ReadBandwidth,
|
||||
"ssds_num_bad_sectors": data.Content.NumBadSectors,
|
||||
}
|
||||
|
||||
acc.AddFields("xio", fields, tags)
|
||||
}
|
||||
|
||||
func (xio *XtremIO) gatherVolumes(acc telegraf.Accumulator, url string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
resp, err := xio.call(url)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := volumes{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"guid": data.Content.GUID,
|
||||
"sys_name": data.Content.SysName,
|
||||
"name": data.Content.Name,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"volumes_read_iops": data.Content.ReadIops,
|
||||
"volumes_write_iops": data.Content.WriteIops,
|
||||
"volumes_read_latency": data.Content.ReadLatency,
|
||||
"volumes_write_latency": data.Content.WriteLatency,
|
||||
"volumes_data_reduction_ratio": data.Content.DataReductionRatio,
|
||||
"volumes_provisioned_space": data.Content.ProvisionedSpace,
|
||||
"volumes_used_space": data.Content.UsedSpace,
|
||||
}
|
||||
|
||||
acc.AddFields("xio", fields, tags)
|
||||
}
|
||||
|
||||
func (xio *XtremIO) gatherXMS(acc telegraf.Accumulator, url string, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
resp, err := xio.call(url)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := xms{}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"guid": data.Content.GUID,
|
||||
"name": data.Content.Name,
|
||||
"version": data.Content.Version,
|
||||
"xms_ip": data.Content.IP,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"xms_write_iops": data.Content.WriteIops,
|
||||
"xms_read_iops": data.Content.ReadIops,
|
||||
"xms_overall_efficiency_ratio": data.Content.EfficiencyRatio,
|
||||
"xms_ssd_space_in_use": data.Content.SpaceUsed,
|
||||
"xms_ram_in_use": data.Content.RAMUsage,
|
||||
"xms_ram_total": data.Content.RAMTotal,
|
||||
"xms_cpu_usage_total": data.Content.CPUUsage,
|
||||
"xms_write_latency": data.Content.WriteLatency,
|
||||
"xms_read_latency": data.Content.ReadLatency,
|
||||
"xms_user_accounts_count": data.Content.NumAccounts,
|
||||
}
|
||||
|
||||
acc.AddFields("xio", fields, tags)
|
||||
}
|
||||
|
||||
func (xio *XtremIO) call(endpoint string) (string, error) {
|
||||
req, err := http.NewRequest("GET", xio.URL+"/api/json/v3/types/"+endpoint, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.AddCookie(xio.cookie)
|
||||
resp, err := xio.client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func (xio *XtremIO) authenticate() error {
|
||||
req, err := http.NewRequest("GET", xio.URL+"/api/json/v3/commands/login", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.SetBasicAuth(xio.Username, xio.Password)
|
||||
resp, err := xio.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
for _, cookie := range resp.Cookies() {
|
||||
if cookie.Name == "sessid" {
|
||||
xio.cookie = cookie
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("xtremio", func() telegraf.Input {
|
||||
return &XtremIO{}
|
||||
})
|
||||
}
|
225
plugins/inputs/xtremio/xtremio_test.go
Normal file
225
plugins/inputs/xtremio/xtremio_test.go
Normal file
|
@ -0,0 +1,225 @@
|
|||
package xtremio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
var testdataDir = getTestdataDir()
|
||||
|
||||
func TestInitDefault(t *testing.T) {
|
||||
// This test should succeed with the default initialization.
|
||||
plugin := &XtremIO{
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
URL: "http://example.com",
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
|
||||
// Test the initialization succeeds
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
// Also test that default values are set correctly
|
||||
require.Equal(t, "testuser", plugin.Username)
|
||||
require.Equal(t, "testpass", plugin.Password)
|
||||
require.Equal(t, "http://example.com", plugin.URL)
|
||||
}
|
||||
|
||||
func TestInitFail(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
plugin *XtremIO
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "all empty",
|
||||
plugin: &XtremIO{},
|
||||
expected: "username cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "no username",
|
||||
plugin: &XtremIO{Password: "testpass", URL: "http://example.com"},
|
||||
expected: "username cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "no password",
|
||||
plugin: &XtremIO{Username: "testuser", URL: "http://example.com"},
|
||||
expected: "password cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "no url",
|
||||
plugin: &XtremIO{Username: "testuser", Password: "testpass"},
|
||||
expected: "url cannot be empty",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.plugin.Log = testutil.Logger{}
|
||||
err := tt.plugin.Init()
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFixedValue(t *testing.T) {
|
||||
ts := httptest.NewServer(
|
||||
http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/api/json/v3/commands/login" {
|
||||
cookie := &http.Cookie{Name: "sessid", Value: "cookie:123456789"}
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
if _, err := fmt.Fprintln(w, "authentication succeeded"); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else if r.URL.Path == "/api/json/v3/types/bbus" {
|
||||
sampleGetBBUsResponse, err := os.ReadFile(filepath.Join(testdataDir, "sample_get_bbu_response.json"))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintln(w, string(sampleGetBBUsResponse)); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else if r.URL.Path == "/api/json/v3/types/bbus/987654321abcdef" {
|
||||
sampleBBUResponseOne, err := os.ReadFile(filepath.Join(testdataDir, "sample_bbu_response.json"))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintln(w, string(sampleBBUResponseOne)); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
defer ts.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
plugin *XtremIO
|
||||
expected []telegraf.Metric
|
||||
}{
|
||||
{
|
||||
name: "gather bbus only",
|
||||
plugin: &XtremIO{
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
URL: ts.URL,
|
||||
Collectors: []string{"bbus"},
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"xio",
|
||||
map[string]string{
|
||||
"serial_number": "A123B45678",
|
||||
"guid": "987654321abcdef",
|
||||
"power_feed": "PWR-A",
|
||||
"name": "X1-BBU",
|
||||
"model_name": "Eaton Model Name",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"bbus_power": 244,
|
||||
"bbus_average_daily_temp": 23,
|
||||
"bbus_enabled": true,
|
||||
"bbus_ups_need_battery_replacement": false,
|
||||
"bbus_ups_low_battery_no_input": false,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
tt.plugin.Log = testutil.Logger{}
|
||||
require.NoError(t, tt.plugin.Init())
|
||||
require.NoError(t, tt.plugin.Gather(&acc))
|
||||
require.Empty(t, acc.Errors, "found errors accumulated by acc.AddError()")
|
||||
acc.Wait(len(tt.expected))
|
||||
testutil.RequireMetricsEqual(t, tt.expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticationFailed(t *testing.T) {
|
||||
ts := httptest.NewServer(
|
||||
http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
if _, err := fmt.Fprintln(w, "bad request"); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
},
|
||||
),
|
||||
)
|
||||
defer ts.Close()
|
||||
tests := []struct {
|
||||
name string
|
||||
plugin *XtremIO
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "authentication failed",
|
||||
plugin: &XtremIO{
|
||||
Username: "usertest",
|
||||
Password: "userpass",
|
||||
URL: ts.URL,
|
||||
},
|
||||
expected: "no authentication cookie set",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
tt.plugin.Log = testutil.Logger{}
|
||||
require.NoError(t, tt.plugin.Init())
|
||||
|
||||
err := tt.plugin.Gather(&acc)
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getTestdataDir() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
// if we cannot even establish the test directory, further progress is meaningless
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return filepath.Join(dir, "testdata")
|
||||
}
|
98
plugins/inputs/xtremio/xtremio_types.go
Normal file
98
plugins/inputs/xtremio/xtremio_types.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
package xtremio
|
||||
|
||||
type bbu struct {
|
||||
Content struct {
|
||||
Serial string `json:"serial-number"`
|
||||
GUID string `json:"guid"`
|
||||
PowerFeed string `json:"power-feed"`
|
||||
Name string `json:"Name"`
|
||||
ModelName string `json:"model-name"`
|
||||
BBUPower int `json:"power"`
|
||||
BBUDailyTemp int `json:"avg-daily-temp"`
|
||||
BBUEnabled string `json:"enabled-state"`
|
||||
BBUNeedBat bool `json:"ups-need-battery-replacement,string"`
|
||||
BBULowBat bool `json:"is-low-battery-no-input,string"`
|
||||
}
|
||||
}
|
||||
|
||||
type clusters struct {
|
||||
Content struct {
|
||||
HardwarePlatform string `json:"hardware-platform"`
|
||||
LicenseID string `json:"license-id"`
|
||||
GUID string `json:"guid"`
|
||||
Name string `json:"name"`
|
||||
SerialNumber string `json:"sys-psnt-serial-number"`
|
||||
CompressionFactor float64 `json:"compression-factor"`
|
||||
MemoryUsed int `json:"total-memory-in-use-in-percent"`
|
||||
ReadIops int `json:"rd-iops,string"`
|
||||
WriteIops int `json:"wr-iops,string"`
|
||||
NumVolumes int `json:"num-of-vols"`
|
||||
FreeSSDSpace int `json:"free-ud-ssd-space-in-percent"`
|
||||
NumSSDs int `json:"num-of-ssds"`
|
||||
DataReductionRatio float64 `json:"data-reduction-ratio"`
|
||||
}
|
||||
}
|
||||
|
||||
type ssd struct {
|
||||
Content struct {
|
||||
ModelName string `json:"model-name"`
|
||||
FirmwareVersion string `json:"fw-version"`
|
||||
SSDuid string `json:"ssd-uid"`
|
||||
GUID string `json:"guid"`
|
||||
SysName string `json:"sys-name"`
|
||||
SerialNumber string `json:"serial-number"`
|
||||
Size int `json:"ssd-size,string"`
|
||||
SpaceUsed int `json:"ssd-space-in-use,string"`
|
||||
WriteIops int `json:"wr-iops,string"`
|
||||
ReadIops int `json:"rd-iops,string"`
|
||||
WriteBandwidth int `json:"wr-bw,string"`
|
||||
ReadBandwidth int `json:"rd-bw,string"`
|
||||
NumBadSectors int `json:"num-bad-sectors"`
|
||||
}
|
||||
}
|
||||
|
||||
type volumes struct {
|
||||
Content struct {
|
||||
GUID string `json:"guid"`
|
||||
SysName string `json:"sys-name"`
|
||||
Name string `json:"name"`
|
||||
ReadIops int `json:"rd-iops,string"`
|
||||
WriteIops int `json:"wr-iops,string"`
|
||||
ReadLatency int `json:"rd-latency,string"`
|
||||
WriteLatency int `json:"wr-latency,string"`
|
||||
DataReductionRatio float64 `json:"data-reduction-ratio,string"`
|
||||
ProvisionedSpace int `json:"vol-size,string"`
|
||||
UsedSpace int `json:"logical-space-in-use,string"`
|
||||
}
|
||||
}
|
||||
|
||||
type xms struct {
|
||||
Content struct {
|
||||
GUID string `json:"guid"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
IP string `json:"xms-ip"`
|
||||
WriteIops int `json:"wr-iops,string"`
|
||||
ReadIops int `json:"rd-iops,string"`
|
||||
EfficiencyRatio float64 `json:"overall-efficiency-ratio,string"`
|
||||
SpaceUsed int `json:"ssd-space-in-use,string"`
|
||||
RAMUsage int `json:"ram-usage,string"`
|
||||
RAMTotal int `json:"ram-total,string"`
|
||||
CPUUsage float64 `json:"cpu"`
|
||||
WriteLatency int `json:"wr-latency,string"`
|
||||
ReadLatency int `json:"rd-latency,string"`
|
||||
NumAccounts int `json:"num-of-user-accounts"`
|
||||
}
|
||||
}
|
||||
|
||||
type href struct {
|
||||
Href string `json:"href"`
|
||||
}
|
||||
|
||||
type collectorResponse struct {
|
||||
BBUs []href `json:"bbus"`
|
||||
Clusters []href `json:"clusters"`
|
||||
SSDs []href `json:"ssds"`
|
||||
Volumes []href `json:"volumes"`
|
||||
XMS []href `json:"xmss"`
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue