summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/scaleio
diff options
context:
space:
mode:
Diffstat (limited to '')
l---------src/go/collectors/go.d.plugin/modules/scaleio/README.md1
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/charts.go465
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/client/client.go316
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/client/client_test.go142
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/client/server.go149
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/client/types.go1096
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/collect.go58
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/collect_sdc.go38
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/collect_storage_pool.go41
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/collect_system.go250
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/config_schema.json177
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/integrations/dell_emc_scaleio.md255
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/metadata.yaml399
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/metrics.go126
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/queries.go111
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/scaleio.go129
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/scaleio_test.go384
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.json20
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.yaml17
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/testdata/instances.json1160
-rw-r--r--src/go/collectors/go.d.plugin/modules/scaleio/testdata/selected_statistics.json777
21 files changed, 6111 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/README.md b/src/go/collectors/go.d.plugin/modules/scaleio/README.md
new file mode 120000
index 000000000..1836d2805
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/README.md
@@ -0,0 +1 @@
+integrations/dell_emc_scaleio.md \ No newline at end of file
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/charts.go b/src/go/collectors/go.d.plugin/modules/scaleio/charts.go
new file mode 100644
index 000000000..a6ac24bd9
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/charts.go
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import (
+ "fmt"
+
+ "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+type (
+ // Charts is an alias for module.Charts.
+ Charts = module.Charts
+ // Dims is an alias for module.Dims.
+ Dims = module.Dims
+ // Vars is an alias for module.Vars.
+ Vars = module.Vars
+)
+
+var (
+ prioStoragePool = module.Priority + len(systemCharts) + 10
+ prioSdc = prioStoragePool + len(storagePoolCharts) + 10
+)
+
+var systemCharts = Charts{
+ // Capacity
+ {
+ ID: "system_capacity_total",
+ Title: "Total Capacity",
+ Units: "KiB",
+ Fam: "capacity",
+ Ctx: "scaleio.system_capacity_total",
+ Dims: Dims{
+ {ID: "system_capacity_max_capacity", Name: "total"},
+ },
+ },
+ {
+ ID: "system_capacity_in_use",
+ Title: "Capacity In Use",
+ Units: "KiB",
+ Fam: "capacity",
+ Ctx: "scaleio.system_capacity_in_use",
+ Dims: Dims{
+ {ID: "system_capacity_in_use", Name: "in_use"},
+ },
+ },
+ {
+ ID: "system_capacity_usage",
+ Title: "Capacity Usage",
+ Units: "KiB",
+ Fam: "capacity",
+ Type: module.Stacked,
+ Ctx: "scaleio.system_capacity_usage",
+ Dims: Dims{
+ {ID: "system_capacity_thick_in_use", Name: "thick"},
+ {ID: "system_capacity_decreased", Name: "decreased"},
+ {ID: "system_capacity_thin_in_use", Name: "thin"},
+ {ID: "system_capacity_snapshot", Name: "snapshot"},
+ {ID: "system_capacity_spare", Name: "spare"},
+ {ID: "system_capacity_unused", Name: "unused"},
+ },
+ },
+ {
+ ID: "system_capacity_available_volume_allocation",
+ Title: "Available For Volume Allocation",
+ Units: "KiB",
+ Fam: "capacity",
+ Ctx: "scaleio.system_capacity_available_volume_allocation",
+ Dims: Dims{
+ {ID: "system_capacity_available_for_volume_allocation", Name: "available"},
+ },
+ },
+ {
+ ID: "system_capacity_health_state",
+ Title: "Capacity Health State",
+ Units: "KiB",
+ Fam: "health",
+ Type: module.Stacked,
+ Ctx: "scaleio.system_capacity_health_state",
+ Dims: Dims{
+ {ID: "system_capacity_protected", Name: "protected"},
+ {ID: "system_capacity_degraded", Name: "degraded"},
+ {ID: "system_capacity_in_maintenance", Name: "in_maintenance"},
+ {ID: "system_capacity_failed", Name: "failed"},
+ {ID: "system_capacity_unreachable_unused", Name: "unavailable"},
+ },
+ },
+ // I/O Workload BW
+ {
+ ID: "system_workload_primary_bandwidth_total",
+ Title: "Primary Backend Bandwidth Total (Read and Write)",
+ Units: "KiB/s",
+ Fam: "workload",
+ Ctx: "scaleio.system_workload_primary_bandwidth_total",
+ Dims: Dims{
+ {ID: "system_backend_primary_bandwidth_read_write", Name: "total", Div: 1000},
+ },
+ },
+ {
+ ID: "system_workload_primary_bandwidth",
+ Title: "Primary Backend Bandwidth",
+ Units: "KiB/s",
+ Fam: "workload",
+ Ctx: "scaleio.system_workload_primary_bandwidth",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "system_backend_primary_bandwidth_read", Name: "read", Div: 1000},
+ {ID: "system_backend_primary_bandwidth_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ // I/O Workload IOPS
+ {
+ ID: "system_workload_primary_iops_total",
+ Title: "Primary Backend IOPS Total (Read and Write)",
+ Units: "iops/s",
+ Fam: "workload",
+ Ctx: "scaleio.system_workload_primary_iops_total",
+ Dims: Dims{
+ {ID: "system_backend_primary_iops_read_write", Name: "total", Div: 1000},
+ },
+ },
+ {
+ ID: "system_workload_primary_iops",
+ Title: "Primary Backend IOPS",
+ Units: "iops/s",
+ Fam: "workload",
+ Ctx: "scaleio.system_workload_primary_iops",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "system_backend_primary_iops_read", Name: "read", Div: 1000},
+ {ID: "system_backend_primary_iops_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "system_workload_primary_io_size_total",
+ Title: "Primary Backend I/O Size Total (Read and Write)",
+ Units: "KiB",
+ Fam: "workload",
+ Ctx: "scaleio.system_workload_primary_io_size_total",
+ Dims: Dims{
+ {ID: "system_backend_primary_io_size_read_write", Name: "io_size", Div: 1000},
+ },
+ },
+ // Rebalance
+ {
+ ID: "system_rebalance",
+ Title: "Rebalance",
+ Units: "KiB/s",
+ Fam: "rebalance",
+ Type: module.Area,
+ Ctx: "scaleio.system_rebalance",
+ Dims: Dims{
+ {ID: "system_rebalance_bandwidth_read", Name: "read", Div: 1000},
+ {ID: "system_rebalance_bandwidth_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "system_rebalance_left",
+ Title: "Rebalance Pending Capacity",
+ Units: "KiB",
+ Fam: "rebalance",
+ Ctx: "scaleio.system_rebalance_left",
+ Dims: Dims{
+ {ID: "system_rebalance_pending_capacity_in_Kb", Name: "left"},
+ },
+ },
+ {
+ ID: "system_rebalance_time_until_finish",
+ Title: "Rebalance Approximate Time Until Finish",
+ Units: "seconds",
+ Fam: "rebalance",
+ Ctx: "scaleio.system_rebalance_time_until_finish",
+ Dims: Dims{
+ {ID: "system_rebalance_time_until_finish", Name: "time"},
+ },
+ },
+ // Rebuild
+ {
+ ID: "system_rebuild",
+ Title: "Rebuild Bandwidth Total (Forward, Backward and Normal)",
+ Units: "KiB/s",
+ Fam: "rebuild",
+ Ctx: "scaleio.system_rebuild",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "system_rebuild_total_bandwidth_read", Name: "read", Div: 1000},
+ {ID: "system_rebuild_total_bandwidth_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "system_rebuild_left",
+ Title: "Rebuild Pending Capacity Total (Forward, Backward and Normal)",
+ Units: "KiB",
+ Fam: "rebuild",
+ Ctx: "scaleio.system_rebuild_left",
+ Dims: Dims{
+ {ID: "system_rebuild_total_pending_capacity_in_Kb", Name: "left"},
+ },
+ },
+ // Components
+ {
+ ID: "system_defined_components",
+ Title: "Components",
+ Units: "components",
+ Fam: "components",
+ Ctx: "scaleio.system_defined_components",
+ Dims: Dims{
+ {ID: "system_num_of_devices", Name: "devices"},
+ {ID: "system_num_of_fault_sets", Name: "fault_sets"},
+ {ID: "system_num_of_protection_domains", Name: "protection_domains"},
+ {ID: "system_num_of_rfcache_devices", Name: "rfcache_devices"},
+ {ID: "system_num_of_sdc", Name: "sdc"},
+ {ID: "system_num_of_sds", Name: "sds"},
+ {ID: "system_num_of_snapshots", Name: "snapshots"},
+ {ID: "system_num_of_storage_pools", Name: "storage_pools"},
+ {ID: "system_num_of_volumes", Name: "volumes"},
+ {ID: "system_num_of_vtrees", Name: "vtrees"},
+ },
+ },
+ {
+ ID: "system_components_volumes_by_type",
+ Title: "Volumes By Type",
+ Units: "volumes",
+ Fam: "components",
+ Ctx: "scaleio.system_components_volumes_by_type",
+ Type: module.Stacked,
+ Dims: Dims{
+ {ID: "system_num_of_thick_base_volumes", Name: "thick"},
+ {ID: "system_num_of_thin_base_volumes", Name: "thin"},
+ },
+ },
+ {
+ ID: "system_components_volumes_by_mapping",
+ Title: "Volumes By Mapping",
+ Units: "volumes",
+ Fam: "components",
+ Ctx: "scaleio.system_components_volumes_by_mapping",
+ Type: module.Stacked,
+ Dims: Dims{
+ {ID: "system_num_of_mapped_volumes", Name: "mapped"},
+ {ID: "system_num_of_unmapped_volumes", Name: "unmapped"},
+ },
+ },
+}
+
+var storagePoolCharts = Charts{
+ {
+ ID: "storage_pool_%s_capacity_total",
+ Title: "Total Capacity",
+ Units: "KiB",
+ Fam: "pool %s",
+ Ctx: "scaleio.storage_pool_capacity_total",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_max_capacity", Name: "total"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_capacity_in_use",
+ Title: "Capacity In Use",
+ Units: "KiB",
+ Fam: "pool %s",
+ Ctx: "scaleio.storage_pool_capacity_in_use",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_in_use", Name: "in_use"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_capacity_usage",
+ Title: "Capacity Usage",
+ Units: "KiB",
+ Fam: "pool %s",
+ Type: module.Stacked,
+ Ctx: "scaleio.storage_pool_capacity_usage",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_thick_in_use", Name: "thick"},
+ {ID: "storage_pool_%s_capacity_decreased", Name: "decreased"},
+ {ID: "storage_pool_%s_capacity_thin_in_use", Name: "thin"},
+ {ID: "storage_pool_%s_capacity_snapshot", Name: "snapshot"},
+ {ID: "storage_pool_%s_capacity_spare", Name: "spare"},
+ {ID: "storage_pool_%s_capacity_unused", Name: "unused"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_capacity_utilization",
+ Title: "Capacity Utilization",
+ Units: "percentage",
+ Fam: "pool %s",
+ Ctx: "scaleio.storage_pool_capacity_utilization",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_utilization", Name: "used", Div: 100},
+ },
+ Vars: Vars{
+ {ID: "storage_pool_%s_capacity_alert_high_threshold"},
+ {ID: "storage_pool_%s_capacity_alert_critical_threshold"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_capacity_available_volume_allocation",
+ Title: "Available For Volume Allocation",
+ Units: "KiB",
+ Fam: "pool %s",
+ Ctx: "scaleio.storage_pool_capacity_available_volume_allocation",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_available_for_volume_allocation", Name: "available"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_capacity_health_state",
+ Title: "Capacity Health State",
+ Units: "KiB",
+ Fam: "pool %s",
+ Type: module.Stacked,
+ Ctx: "scaleio.storage_pool_capacity_health_state",
+ Dims: Dims{
+ {ID: "storage_pool_%s_capacity_protected", Name: "protected"},
+ {ID: "storage_pool_%s_capacity_degraded", Name: "degraded"},
+ {ID: "storage_pool_%s_capacity_in_maintenance", Name: "in_maintenance"},
+ {ID: "storage_pool_%s_capacity_failed", Name: "failed"},
+ {ID: "storage_pool_%s_capacity_unreachable_unused", Name: "unavailable"},
+ },
+ },
+ {
+ ID: "storage_pool_%s_components",
+ Title: "Components",
+ Units: "components",
+ Fam: "pool %s",
+ Ctx: "scaleio.storage_pool_components",
+ Dims: Dims{
+ {ID: "storage_pool_%s_num_of_devices", Name: "devices"},
+ {ID: "storage_pool_%s_num_of_snapshots", Name: "snapshots"},
+ {ID: "storage_pool_%s_num_of_volumes", Name: "volumes"},
+ {ID: "storage_pool_%s_num_of_vtrees", Name: "vtrees"},
+ },
+ },
+}
+
+func newStoragePoolCharts(pool client.StoragePool) *Charts {
+ charts := storagePoolCharts.Copy()
+ for i, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, pool.ID)
+ chart.Fam = fmt.Sprintf(chart.Fam, pool.Name)
+ chart.Priority = prioStoragePool + i
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, pool.ID)
+ }
+ for _, v := range chart.Vars {
+ v.ID = fmt.Sprintf(v.ID, pool.ID)
+ }
+ }
+ return charts
+}
+
+var sdcCharts = Charts{
+ {
+ ID: "sdc_%s_mdm_connection_state",
+ Title: "MDM Connection State",
+ Units: "boolean",
+ Fam: "sdc %s",
+ Ctx: "scaleio.sdc_mdm_connection_state",
+ Dims: Dims{
+ {ID: "sdc_%s_mdm_connection_state", Name: "connected"},
+ },
+ },
+ {
+ ID: "sdc_%s_bandwidth",
+ Title: "Bandwidth",
+ Units: "KiB/s",
+ Fam: "sdc %s",
+ Ctx: "scaleio.sdc_bandwidth",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "sdc_%s_bandwidth_read", Name: "read", Div: 1000},
+ {ID: "sdc_%s_bandwidth_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "sdc_%s_iops",
+ Title: "IOPS",
+ Units: "iops/s",
+ Fam: "sdc %s",
+ Ctx: "scaleio.sdc_iops",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "sdc_%s_iops_read", Name: "read", Div: 1000},
+ {ID: "sdc_%s_iops_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "sdc_%s_io_size",
+ Title: "I/O Size",
+ Units: "KiB",
+ Fam: "sdc %s",
+ Ctx: "scaleio.sdc_io_size",
+ Type: module.Area,
+ Dims: Dims{
+ {ID: "sdc_%s_io_size_read", Name: "read", Div: 1000},
+ {ID: "sdc_%s_io_size_write", Name: "write", Mul: -1, Div: 1000},
+ },
+ },
+ {
+ ID: "sdc_%s_num_of_mapped_volumed",
+ Title: "Mapped Volumes",
+ Units: "volumes",
+ Fam: "sdc %s",
+ Ctx: "scaleio.sdc_num_of_mapped_volumed",
+ Dims: Dims{
+ {ID: "sdc_%s_num_of_mapped_volumes", Name: "mapped"},
+ },
+ },
+}
+
+func newSdcCharts(sdc client.Sdc) *Charts {
+ charts := sdcCharts.Copy()
+ for i, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, sdc.ID)
+ chart.Fam = fmt.Sprintf(chart.Fam, sdc.SdcIp)
+ chart.Priority = prioSdc + i
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, sdc.ID)
+ }
+ }
+ return charts
+}
+
+// TODO: remove stale charts?
+func (s *ScaleIO) updateCharts() {
+ s.updateStoragePoolCharts()
+ s.updateSdcCharts()
+}
+
+func (s *ScaleIO) updateStoragePoolCharts() {
+ for _, pool := range s.discovered.pool {
+ if s.charted[pool.ID] {
+ continue
+ }
+ s.charted[pool.ID] = true
+ s.addStoragePoolCharts(pool)
+ }
+}
+
+func (s *ScaleIO) updateSdcCharts() {
+ for _, sdc := range s.discovered.sdc {
+ if s.charted[sdc.ID] {
+ continue
+ }
+ s.charted[sdc.ID] = true
+ s.addSdcCharts(sdc)
+ }
+}
+
+func (s *ScaleIO) addStoragePoolCharts(pool client.StoragePool) {
+ charts := newStoragePoolCharts(pool)
+ if err := s.Charts().Add(*charts...); err != nil {
+ s.Warningf("couldn't add charts for storage pool '%s(%s)': %v", pool.ID, pool.Name, err)
+ }
+}
+
+func (s *ScaleIO) addSdcCharts(sdc client.Sdc) {
+ charts := newSdcCharts(sdc)
+ if err := s.Charts().Add(*charts...); err != nil {
+ s.Warningf("couldn't add charts for sdc '%s(%s)': %v", sdc.ID, sdc.SdcIp, err)
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/client/client.go b/src/go/collectors/go.d.plugin/modules/scaleio/client/client.go
new file mode 100644
index 000000000..e60dfbf68
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/client/client.go
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/web"
+)
+
+/*
+The REST API is served from the VxFlex OS Gateway.
+The FxFlex Gateway connects to a single MDM and serves requests by querying the MDM
+and reformatting the answers it receives from the MDM in s RESTful manner, back to a REST API.
+The Gateway is stateless. It requires the MDM username and password for the login requests.
+The login returns a token in the response, that is used for later authentication for other requests.
+
+The token is valid for 8 hours from the time it was created, unless there has been no activity
+for 10 minutes, of if the client has sent a logout request.
+
+General URI:
+- /api/login
+- /api/logout
+- /api/version
+- /api/instances/ // GET all instances
+- /api/types/{type}/instances // POST (create) / GET all objects for a given type
+- /api/instances/{type::id} // GET by ID
+- /api/instances/{type::id}/relationships/{Relationship name} // GET
+- /api/instances/querySelectedStatistics // POST Query selected statistics
+- /api/instances/{type::id}/action/{actionName} // POST a special action on an object
+- /api/types/{type}/instances/action/{actionName} // POST a special action on a given type
+
+Types:
+- System
+- Sds
+- StoragePool
+- ProtectionDomain
+- Device
+- Volume
+- VTree
+- Sdc
+- User
+- FaultSet
+- RfcacheDevice
+- Alerts
+
+Actions:
+- querySelectedStatistics // All types except Alarm and User
+- querySystemLimits // System
+- queryDisconnectedSdss // Sds
+- querySdsNetworkLatencyMeters // Sds
+- queryFailedDevices" // Device. Note: works strange!
+
+Relationships:
+- Statistics // All types except Alarm and User
+- ProtectionDomain // System
+- Sdc // System
+- User // System
+- StoragePool // ProtectionDomain
+- FaultSet // ProtectionDomain
+- Sds // ProtectionDomain
+- RfcacheDevice // Sds
+- Device // Sds, StoragePool
+- Volume // Sdc, StoragePool
+- VTree // StoragePool
+*/
+
+// New creates new ScaleIO client.
+func New(client web.Client, request web.Request) (*Client, error) {
+ httpClient, err := web.NewHTTPClient(client)
+ if err != nil {
+ return nil, err
+ }
+ return &Client{
+ Request: request,
+ httpClient: httpClient,
+ token: newToken(),
+ }, nil
+}
+
+// Client represents ScaleIO client.
+type Client struct {
+ Request web.Request
+ httpClient *http.Client
+ token *token
+}
+
+// LoggedIn reports whether the client is logged in.
+func (c *Client) LoggedIn() bool {
+ return c.token.isSet()
+}
+
+// Login connects to FxFlex Gateway to get the token that is used for later authentication for other requests.
+func (c *Client) Login() error {
+ if c.LoggedIn() {
+ _ = c.Logout()
+ }
+ req := c.createLoginRequest()
+ resp, err := c.doOK(req)
+ defer closeBody(resp)
+ if err != nil {
+ return err
+ }
+
+ token, err := decodeToken(resp.Body)
+ if err != nil {
+ return err
+ }
+
+ c.token.set(token)
+ return nil
+}
+
+// Logout sends logout request and unsets token.
+func (c *Client) Logout() error {
+ if !c.LoggedIn() {
+ return nil
+ }
+ req := c.createLogoutRequest()
+ c.token.unset()
+
+ resp, err := c.do(req)
+ defer closeBody(resp)
+ return err
+}
+
+// APIVersion returns FxFlex Gateway API version.
+func (c *Client) APIVersion() (Version, error) {
+ req := c.createAPIVersionRequest()
+ resp, err := c.doOK(req)
+ defer closeBody(resp)
+ if err != nil {
+ return Version{}, err
+ }
+ return decodeVersion(resp.Body)
+}
+
+// SelectedStatistics returns selected statistics.
+func (c *Client) SelectedStatistics(query SelectedStatisticsQuery) (SelectedStatistics, error) {
+ b, _ := json.Marshal(query)
+ req := c.createSelectedStatisticsRequest(b)
+ var stats SelectedStatistics
+ err := c.doJSONWithRetry(&stats, req)
+ return stats, err
+}
+
+// Instances returns all instances.
+func (c *Client) Instances() (Instances, error) {
+ req := c.createInstancesRequest()
+ var instances Instances
+ err := c.doJSONWithRetry(&instances, req)
+ return instances, err
+}
+
+func (c *Client) createLoginRequest() web.Request {
+ req := c.Request.Copy()
+ u, _ := url.Parse(req.URL)
+ u.Path = path.Join(u.Path, "/api/login")
+ req.URL = u.String()
+ return req
+}
+
+func (c *Client) createLogoutRequest() web.Request {
+ req := c.Request.Copy()
+ u, _ := url.Parse(req.URL)
+ u.Path = path.Join(u.Path, "/api/logout")
+ req.URL = u.String()
+ req.Password = c.token.get()
+ return req
+}
+
+func (c *Client) createAPIVersionRequest() web.Request {
+ req := c.Request.Copy()
+ u, _ := url.Parse(req.URL)
+ u.Path = path.Join(u.Path, "/api/version")
+ req.URL = u.String()
+ req.Password = c.token.get()
+ return req
+}
+
+func (c *Client) createSelectedStatisticsRequest(query []byte) web.Request {
+ req := c.Request.Copy()
+ u, _ := url.Parse(req.URL)
+ u.Path = path.Join(u.Path, "/api/instances/querySelectedStatistics")
+ req.URL = u.String()
+ req.Password = c.token.get()
+ req.Method = http.MethodPost
+ req.Headers = map[string]string{
+ "Content-Type": "application/json",
+ }
+ req.Body = string(query)
+ return req
+}
+
+func (c *Client) createInstancesRequest() web.Request {
+ req := c.Request.Copy()
+ u, _ := url.Parse(req.URL)
+ u.Path = path.Join(u.Path, "/api/instances")
+ req.URL = u.String()
+ req.Password = c.token.get()
+ return req
+}
+
+func (c *Client) do(req web.Request) (*http.Response, error) {
+ httpReq, err := web.NewHTTPRequest(req)
+ if err != nil {
+ return nil, fmt.Errorf("error on creating http request to %s: %v", req.URL, err)
+ }
+ return c.httpClient.Do(httpReq)
+}
+
+func (c *Client) doOK(req web.Request) (*http.Response, error) {
+ resp, err := c.do(req)
+ if err != nil {
+ return nil, err
+ }
+ if err = checkStatusCode(resp); err != nil {
+ err = fmt.Errorf("%s returned %v", req.URL, err)
+ }
+ return resp, err
+}
+
+func (c *Client) doOKWithRetry(req web.Request) (*http.Response, error) {
+ resp, err := c.do(req)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode == http.StatusUnauthorized {
+ if err = c.Login(); err != nil {
+ return resp, err
+ }
+ req.Password = c.token.get()
+ return c.doOK(req)
+ }
+ if err = checkStatusCode(resp); err != nil {
+ err = fmt.Errorf("%s returned %v", req.URL, err)
+ }
+ return resp, err
+}
+
+func (c *Client) doJSONWithRetry(dst interface{}, req web.Request) error {
+ resp, err := c.doOKWithRetry(req)
+ defer closeBody(resp)
+ if err != nil {
+ return err
+ }
+ return json.NewDecoder(resp.Body).Decode(dst)
+}
+
+func closeBody(resp *http.Response) {
+ if resp != nil && resp.Body != nil {
+ _, _ = io.Copy(io.Discard, resp.Body)
+ _ = resp.Body.Close()
+ }
+}
+
+func checkStatusCode(resp *http.Response) error {
+ // For all 4xx and 5xx return codes, the body may contain an apiError
+ // instance with more specifics about the failure.
+ if resp.StatusCode >= 400 {
+ e := error(&apiError{})
+ if err := json.NewDecoder(resp.Body).Decode(e); err != nil {
+ e = err
+ }
+ return fmt.Errorf("HTTP status code %d : %v", resp.StatusCode, e)
+ }
+
+ // 200(OK), 201(Created), 202(Accepted), 204 (No Content).
+ if resp.StatusCode < 200 || resp.StatusCode > 299 {
+ return fmt.Errorf("HTTP status code %d", resp.StatusCode)
+ }
+ return nil
+}
+
+func decodeVersion(reader io.Reader) (ver Version, err error) {
+ bs, err := io.ReadAll(reader)
+ if err != nil {
+ return ver, err
+ }
+ parts := strings.Split(strings.Trim(string(bs), "\n "), ".")
+ if len(parts) != 2 {
+ return ver, fmt.Errorf("can't parse: %s", string(bs))
+ }
+ if ver.Major, err = strconv.ParseInt(parts[0], 10, 64); err != nil {
+ return ver, err
+ }
+ ver.Minor, err = strconv.ParseInt(parts[1], 10, 64)
+ return ver, err
+}
+
+func decodeToken(reader io.Reader) (string, error) {
+ bs, err := io.ReadAll(reader)
+ if err != nil {
+ return "", err
+ }
+ return strings.Trim(string(bs), `"`), nil
+}
+
+type token struct {
+ mux *sync.RWMutex
+ value string
+}
+
+func newToken() *token { return &token{mux: &sync.RWMutex{}} }
+func (t *token) get() string { t.mux.RLock(); defer t.mux.RUnlock(); return t.value }
+func (t *token) set(v string) { t.mux.Lock(); defer t.mux.Unlock(); t.value = v }
+func (t *token) unset() { t.set("") }
+func (t *token) isSet() bool { return t.get() != "" }
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/client/client_test.go b/src/go/collectors/go.d.plugin/modules/scaleio/client/client_test.go
new file mode 100644
index 000000000..ea82814c2
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/client/client_test.go
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package client
+
+import (
+ "net/http/httptest"
+ "testing"
+
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/web"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNew(t *testing.T) {
+ _, err := New(web.Client{}, web.Request{})
+ assert.NoError(t, err)
+}
+
+func TestClient_Login(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ assert.NoError(t, client.Login())
+ assert.Equal(t, testToken, client.token.get())
+}
+
+func TestClient_Logout(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ require.NoError(t, client.Login())
+
+ assert.NoError(t, client.Logout())
+ assert.False(t, client.token.isSet())
+
+}
+
+func TestClient_LoggedIn(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ assert.False(t, client.LoggedIn())
+ assert.NoError(t, client.Login())
+ assert.True(t, client.LoggedIn())
+}
+
+func TestClient_APIVersion(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ err := client.Login()
+ require.NoError(t, err)
+
+ version, err := client.APIVersion()
+ assert.NoError(t, err)
+ assert.Equal(t, Version{Major: 2, Minor: 5}, version)
+}
+
+func TestClient_Instances(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ err := client.Login()
+ require.NoError(t, err)
+
+ instances, err := client.Instances()
+ assert.NoError(t, err)
+ assert.Equal(t, testInstances, instances)
+}
+
+func TestClient_Instances_RetryOnExpiredToken(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ instances, err := client.Instances()
+ assert.NoError(t, err)
+ assert.Equal(t, testInstances, instances)
+}
+
+func TestClient_SelectedStatistics(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ err := client.Login()
+ require.NoError(t, err)
+
+ stats, err := client.SelectedStatistics(SelectedStatisticsQuery{})
+ assert.NoError(t, err)
+ assert.Equal(t, testStatistics, stats)
+}
+
+func TestClient_SelectedStatistics_RetryOnExpiredToken(t *testing.T) {
+ srv, client := prepareSrvClient(t)
+ defer srv.Close()
+
+ stats, err := client.SelectedStatistics(SelectedStatisticsQuery{})
+ assert.Equal(t, testStatistics, stats)
+ assert.NoError(t, err)
+ assert.Equal(t, testStatistics, stats)
+}
+
+func prepareSrvClient(t *testing.T) (*httptest.Server, *Client) {
+ t.Helper()
+ srv := httptest.NewServer(MockScaleIOAPIServer{
+ User: testUser,
+ Password: testPassword,
+ Version: testVersion,
+ Token: testToken,
+ Instances: testInstances,
+ Statistics: testStatistics,
+ })
+ client, err := New(web.Client{}, web.Request{
+ URL: srv.URL,
+ Username: testUser,
+ Password: testPassword,
+ })
+ assert.NoError(t, err)
+ return srv, client
+}
+
+var (
+ testUser = "user"
+ testPassword = "password"
+ testVersion = "2.5"
+ testToken = "token"
+ testInstances = Instances{
+ StoragePoolList: []StoragePool{
+ {ID: "id1", Name: "Marketing", SparePercentage: 10},
+ {ID: "id2", Name: "Finance", SparePercentage: 10},
+ },
+ SdcList: []Sdc{
+ {ID: "id1", SdcIp: "10.0.0.1", MdmConnectionState: "Connected"},
+ {ID: "id2", SdcIp: "10.0.0.2", MdmConnectionState: "Connected"},
+ },
+ }
+ testStatistics = SelectedStatistics{
+ System: SystemStatistics{NumOfDevices: 1},
+ Sdc: map[string]SdcStatistics{"id1": {}, "id2": {}},
+ StoragePool: map[string]StoragePoolStatistics{"id1": {}, "id2": {}},
+ }
+)
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/client/server.go b/src/go/collectors/go.d.plugin/modules/scaleio/client/server.go
new file mode 100644
index 000000000..b7269d339
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/client/server.go
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+// MockScaleIOAPIServer represents VxFlex OS Gateway.
+type MockScaleIOAPIServer struct {
+ User string
+ Password string
+ Token string
+ Version string
+ Instances Instances
+ Statistics SelectedStatistics
+}
+
+func (s MockScaleIOAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.Path {
+ default:
+ w.WriteHeader(http.StatusNotFound)
+ msg := fmt.Sprintf("unknown URL path: %s", r.URL.Path)
+ writeAPIError(w, msg)
+ case "/api/login":
+ s.handleLogin(w, r)
+ case "/api/logout":
+ s.handleLogout(w, r)
+ case "/api/version":
+ s.handleVersion(w, r)
+ case "/api/instances":
+ s.handleInstances(w, r)
+ case "/api/instances/querySelectedStatistics":
+ s.handleQuerySelectedStatistics(w, r)
+ }
+}
+
+func (s MockScaleIOAPIServer) handleLogin(w http.ResponseWriter, r *http.Request) {
+ if user, pass, ok := r.BasicAuth(); !ok || user != s.User || pass != s.Password {
+ w.WriteHeader(http.StatusUnauthorized)
+ msg := fmt.Sprintf("user got/expected: %s/%s, pass got/expected: %s/%s", user, s.User, pass, s.Password)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("wrong method: '%s', expected '%s'", r.Method, http.MethodGet)
+ writeAPIError(w, msg)
+ return
+ }
+ _, _ = w.Write([]byte(s.Token))
+}
+
+func (s MockScaleIOAPIServer) handleLogout(w http.ResponseWriter, r *http.Request) {
+ if _, pass, ok := r.BasicAuth(); !ok || pass != s.Token {
+ w.WriteHeader(http.StatusUnauthorized)
+ msg := fmt.Sprintf("token got/expected: %s/%s", pass, s.Token)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("wrong method: '%s', expected '%s'", r.Method, http.MethodGet)
+ writeAPIError(w, msg)
+ return
+ }
+}
+
+func (s MockScaleIOAPIServer) handleVersion(w http.ResponseWriter, r *http.Request) {
+ if _, pass, ok := r.BasicAuth(); !ok || pass != s.Token {
+ w.WriteHeader(http.StatusUnauthorized)
+ msg := fmt.Sprintf("token got/expected: %s/%s", pass, s.Token)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("wrong method: '%s', expected '%s'", r.Method, http.MethodGet)
+ writeAPIError(w, msg)
+ return
+ }
+ _, _ = w.Write([]byte(s.Version))
+}
+
+func (s MockScaleIOAPIServer) handleInstances(w http.ResponseWriter, r *http.Request) {
+ if _, pass, ok := r.BasicAuth(); !ok || pass != s.Token {
+ w.WriteHeader(http.StatusUnauthorized)
+ msg := fmt.Sprintf("token got/expected: %s/%s", pass, s.Token)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("wrong method: '%s', expected '%s'", r.Method, http.MethodGet)
+ writeAPIError(w, msg)
+ return
+ }
+ b, err := json.Marshal(s.Instances)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ msg := fmt.Sprintf("marshal Instances: %v", err)
+ writeAPIError(w, msg)
+ return
+ }
+ _, _ = w.Write(b)
+}
+
+func (s MockScaleIOAPIServer) handleQuerySelectedStatistics(w http.ResponseWriter, r *http.Request) {
+ if _, pass, ok := r.BasicAuth(); !ok || pass != s.Token {
+ w.WriteHeader(http.StatusUnauthorized)
+ msg := fmt.Sprintf("token got/expected: %s/%s", pass, s.Token)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Method != http.MethodPost {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("wrong method: '%s', expected '%s'", r.Method, http.MethodPost)
+ writeAPIError(w, msg)
+ return
+ }
+ if r.Header.Get("Content-Type") != "application/json" {
+ w.WriteHeader(http.StatusBadRequest)
+ writeAPIError(w, "no \"Content-Type: application/json\" in the header")
+ return
+ }
+ if err := json.NewDecoder(r.Body).Decode(&SelectedStatisticsQuery{}); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ msg := fmt.Sprintf("body decode error: %v", err)
+ writeAPIError(w, msg)
+ return
+ }
+ b, err := json.Marshal(s.Statistics)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ msg := fmt.Sprintf("marshal SelectedStatistics: %v", err)
+ writeAPIError(w, msg)
+ return
+ }
+ _, _ = w.Write(b)
+}
+
+func writeAPIError(w io.Writer, msg string) {
+ err := apiError{Message: msg}
+ b, _ := json.Marshal(err)
+ _, _ = w.Write(b)
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/client/types.go b/src/go/collectors/go.d.plugin/modules/scaleio/client/types.go
new file mode 100644
index 000000000..c85bddf8d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/client/types.go
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package client
+
+// https://github.com/dell/goscaleio/blob/master/types/v1/types.go
+
+// For all 4xx and 5xx return codes, the body may contain an apiError instance
+// with more specifics about the failure.
+type apiError struct {
+ Message string
+ HTTPStatusCode int
+ ErrorCode int
+}
+
+func (e apiError) Error() string {
+ return e.Message
+}
+
+// Version represents API version.
+type Version struct {
+ Major int64
+ Minor int64
+}
+
+// Bwc Bwc.
+type Bwc struct {
+ NumOccured int64
+ NumSeconds int64
+ TotalWeightInKb int64
+}
+
+// Sdc represents ScaleIO Data Client.
+type Sdc struct {
+ ID string
+ SdcIp string
+ MdmConnectionState string
+}
+
+// StoragePool represents ScaleIO Storage Pool.
+type StoragePool struct {
+ ID string
+ Name string
+ SparePercentage int64
+ CapacityAlertCriticalThreshold int64
+ CapacityAlertHighThreshold int64
+}
+
+// Instances represents '/api/instances' response.
+type Instances struct {
+ StoragePoolList []StoragePool
+ SdcList []Sdc
+}
+
+type (
+ // SelectedStatisticsQuery represents '/api/instances/querySelectedStatistics' query.
+ SelectedStatisticsQuery struct {
+ List []SelectedObject `json:"selectedStatisticsList"`
+ }
+ // SelectedObject represents '/api/instances/querySelectedStatistics' query object.
+ SelectedObject struct {
+ Type string `json:"type"` // object type (System, ProtectionDomain, Sds, StoragePool, Device, Volume, VTree, Sdc, FaultSet, RfcacheDevice).
+
+ // the following parameters are not relevant to the System type and can be omitted:
+ IDs []string `json:"ids,omitempty"` // list of objects ids
+ AllIDs allIds `json:"allIds,omitempty"` // all available objects
+
+ Properties []string `json:"properties"` // list of properties to fetch
+ }
+ allIds bool
+)
+
+func (b allIds) MarshalJSON() ([]byte, error) {
+ // should be set to empty value if AllIDs is true.
+ if b {
+ return []byte("[]"), nil
+ }
+ return nil, nil
+}
+func (b *allIds) UnmarshalJSON([]byte) error {
+ *b = true
+ return nil
+}
+
+// SelectedStatistics represents '/api/instances/querySelectedStatistics' response.
+type SelectedStatistics struct {
+ System SystemStatistics
+ Sdc map[string]SdcStatistics
+ StoragePool map[string]StoragePoolStatistics
+}
+
+// Those commented out structure fields are not deleted on purpose. We need them to see what other metrics can be collected.
+type (
+ // CapacityStatistics is System/StoragePool capacity statistics.
+ CapacityStatistics struct {
+ CapacityAvailableForVolumeAllocationInKb int64
+ MaxCapacityInKb int64
+ CapacityLimitInKb int64
+ ProtectedCapacityInKb int64
+ DegradedFailedCapacityInKb int64
+ DegradedHealthyCapacityInKb int64
+ SpareCapacityInKb int64
+ FailedCapacityInKb int64
+ UnreachableUnusedCapacityInKb int64
+ InMaintenanceCapacityInKb int64
+ ThinCapacityAllocatedInKb int64
+ ThinCapacityInUseInKb int64
+ ThickCapacityInUseInKb int64
+ SnapCapacityInUseOccupiedInKb int64
+ CapacityInUseInKb int64
+ }
+ SystemStatistics struct {
+ CapacityStatistics
+
+ NumOfDevices int64
+ NumOfFaultSets int64
+ NumOfProtectionDomains int64
+ NumOfRfcacheDevices int64
+ NumOfSdc int64
+ NumOfSds int64
+ NumOfSnapshots int64
+ NumOfStoragePools int64
+ NumOfVolumes int64
+ NumOfVtrees int64
+ NumOfThickBaseVolumes int64
+ NumOfThinBaseVolumes int64
+ NumOfMappedToAllVolumes int64
+ NumOfUnmappedVolumes int64
+
+ RebalanceReadBwc Bwc
+ RebalanceWriteBwc Bwc
+ PendingRebalanceCapacityInKb int64
+
+ PendingNormRebuildCapacityInKb int64
+ PendingBckRebuildCapacityInKb int64
+ PendingFwdRebuildCapacityInKb int64
+ NormRebuildReadBwc Bwc // TODO: ???
+ NormRebuildWriteBwc Bwc // TODO: ???
+ BckRebuildReadBwc Bwc // failed node/disk is back alive
+ BckRebuildWriteBwc Bwc // failed node/disk is back alive
+ FwdRebuildReadBwc Bwc // node/disk fails
+ FwdRebuildWriteBwc Bwc // node/disk fails
+
+ PrimaryReadBwc Bwc // Backend (SDSs + Devices) Primary - Mater MDM
+ PrimaryWriteBwc Bwc // Backend (SDSs + Devices) Primary - Mater MDM
+ SecondaryReadBwc Bwc // Backend (SDSs + Devices, 2nd) Secondary - Slave MDM
+ SecondaryWriteBwc Bwc // Backend (SDSs + Devices, 2nd) Secondary - Slave MDM
+ UserDataReadBwc Bwc // Frontend (Volumes + SDCs)
+ UserDataWriteBwc Bwc // Frontend (Volumes + SDCs)
+ TotalReadBwc Bwc // *ReadBwc
+ TotalWriteBwc Bwc // *WriteBwc
+
+ //SnapCapacityInUseInKb int64
+ //BackgroundScanCompareCount int64
+ //BackgroundScannedInMB int64
+ //ActiveBckRebuildCapacityInKb int64
+ //ActiveFwdRebuildCapacityInKb int64
+ //ActiveMovingCapacityInKb int64
+ //ActiveMovingInBckRebuildJobs int64
+ //ActiveMovingInFwdRebuildJobs int64
+ //ActiveMovingInNormRebuildJobs int64
+ //ActiveMovingInRebalanceJobs int64
+ //ActiveMovingOutBckRebuildJobs int64
+ //ActiveMovingOutFwdRebuildJobs int64
+ //ActiveMovingOutNormRebuildJobs int64
+ //ActiveMovingRebalanceJobs int64
+ //ActiveNormRebuildCapacityInKb int64
+ //ActiveRebalanceCapacityInKb int64
+ //AtRestCapacityInKb int64
+ //BckRebuildCapacityInKb int64
+ //DegradedFailedVacInKb int64
+ //DegradedHealthyVacInKb int64
+ //FailedVacInKb int64
+ //FixedReadErrorCount int64
+ //FwdRebuildCapacityInKb int64
+ //InMaintenanceVacInKb int64
+ //InUseVacInKb int64
+ //MovingCapacityInKb int64
+ //NormRebuildCapacityInKb int64
+ //NumOfScsiInitiators int64 // removed from version 3 of ScaleIO/VxFlex API
+ //PendingMovingCapacityInKb int64
+ //PendingMovingInBckRebuildJobs int64
+ //PendingMovingInFwdRebuildJobs int64
+ //PendingMovingInNormRebuildJobs int64
+ //PendingMovingInRebalanceJobs int64
+ //PendingMovingOutBckRebuildJobs int64
+ //PendingMovingOutFwdRebuildJobs int64
+ //PendingMovingOutNormrebuildJobs int64
+ //PendingMovingRebalanceJobs int64
+ //PrimaryReadFromDevBwc int64
+ //PrimaryReadFromRmcacheBwc int64
+ //PrimaryVacInKb int64
+ //ProtectedVacInKb int64
+ //ProtectionDomainIds int64
+ //RebalanceCapacityInKb int64
+ //RebalancePerReceiveJobNetThrottlingInKbps int64
+ //RebalanceWaitSendQLength int64
+ //RebuildPerReceiveJobNetThrottlingInKbps int64
+ //RebuildWaitSendQLength int64
+ //RfacheReadHit int64
+ //RfacheWriteHit int64
+ //RfcacheAvgReadTime int64
+ //RfcacheAvgWriteTime int64
+ //RfcacheFdAvgReadTime int64
+ //RfcacheFdAvgWriteTime int64
+ //RfcacheFdCacheOverloaded int64
+ //RfcacheFdInlightReads int64
+ //RfcacheFdInlightWrites int64
+ //RfcacheFdIoErrors int64
+ //RfcacheFdMonitorErrorStuckIo int64
+ //RfcacheFdReadTimeGreater1Min int64
+ //RfcacheFdReadTimeGreater1Sec int64
+ //RfcacheFdReadTimeGreater500Millis int64
+ //RfcacheFdReadTimeGreater5Sec int64
+ //RfcacheFdReadsReceived int64
+ //RfcacheFdWriteTimeGreater1Min int64
+ //RfcacheFdWriteTimeGreater1Sec int64
+ //RfcacheFdWriteTimeGreater500Millis int64
+ //RfcacheFdWriteTimeGreater5Sec int64
+ //RfcacheFdWritesReceived int64
+ //RfcacheIoErrors int64
+ //RfcacheIosOutstanding int64
+ //RfcacheIosSkipped int64
+ //RfcachePooIosOutstanding int64
+ //RfcachePoolCachePages int64
+ //RfcachePoolEvictions int64
+ //RfcachePoolInLowMemoryCondition int64
+ //RfcachePoolIoTimeGreater1Min int64
+ //RfcachePoolLockTimeGreater1Sec int64
+ //RfcachePoolLowResourcesInitiatedPassthroughMode int64
+ //RfcachePoolNumCacheDevs int64
+ //RfcachePoolNumSrcDevs int64
+ //RfcachePoolPagesInuse int64
+ //RfcachePoolReadHit int64
+ //RfcachePoolReadMiss int64
+ //RfcachePoolReadPendingG10Millis int64
+ //RfcachePoolReadPendingG1Millis int64
+ //RfcachePoolReadPendingG1Sec int64
+ //RfcachePoolReadPendingG500Micro int64
+ //RfcachePoolReadsPending int64
+ //RfcachePoolSize int64
+ //RfcachePoolSourceIdMismatch int64
+ //RfcachePoolSuspendedIos int64
+ //RfcachePoolSuspendedPequestsRedundantSearchs int64
+ //RfcachePoolWriteHit int64
+ //RfcachePoolWriteMiss int64
+ //RfcachePoolWritePending int64
+ //RfcachePoolWritePendingG10Millis int64
+ //RfcachePoolWritePendingG1Millis int64
+ //RfcachePoolWritePendingG1Sec int64
+ //RfcachePoolWritePendingG500Micro int64
+ //RfcacheReadMiss int64
+ //RfcacheReadsFromCache int64
+ //RfcacheReadsPending int64
+ //RfcacheReadsReceived int64
+ //RfcacheReadsSkipped int64
+ //RfcacheReadsSkippedAlignedSizeTooLarge int64
+ //RfcacheReadsSkippedHeavyLoad int64
+ //RfcacheReadsSkippedInternalError int64
+ //RfcacheReadsSkippedLockIos int64
+ //RfcacheReadsSkippedLowResources int64
+ //RfcacheReadsSkippedMaxIoSize int64
+ //RfcacheReadsSkippedStuckIo int64
+ //RfcacheSkippedUnlinedWrite int64
+ //RfcacheSourceDeviceReads int64
+ //RfcacheSourceDeviceWrites int64
+ //RfcacheWriteMiss int64
+ //RfcacheWritePending int64
+ //RfcacheWritesReceived int64
+ //RfcacheWritesSkippedCacheMiss int64
+ //RfcacheWritesSkippedHeavyLoad int64
+ //RfcacheWritesSkippedInternalError int64
+ //RfcacheWritesSkippedLowResources int64
+ //RfcacheWritesSkippedMaxIoSize int64
+ //RfcacheWritesSkippedStuckIo int64
+ //RmPendingAllocatedInKb int64
+ //Rmcache128kbEntryCount int64
+ //Rmcache16kbEntryCount int64
+ //Rmcache32kbEntryCount int64
+ //Rmcache4kbEntryCount int64
+ //Rmcache64kbEntryCount int64
+ //Rmcache8kbEntryCount int64
+ //RmcacheBigBlockEvictionCount int64
+ //RmcacheBigBlockEvictionSizeCountInKb int64
+ //RmcacheCurrNumOf128kbEntries int64
+ //RmcacheCurrNumOf16kbEntries int64
+ //RmcacheCurrNumOf32kbEntries int64
+ //RmcacheCurrNumOf4kbEntries int64
+ //RmcacheCurrNumOf64kbEntries int64
+ //RmcacheCurrNumOf8kbEntries int64
+ //RmcacheEntryEvictionCount int64
+ //RmcacheEntryEvictionSizeCountInKb int64
+ //RmcacheNoEvictionCount int64
+ //RmcacheSizeInKb int64
+ //RmcacheSizeInUseInKb int64
+ //RmcacheSkipCountCacheAllBusy int64
+ //RmcacheSkipCountLargeIo int64
+ //RmcacheSkipCountUnaligned4kbIo int64
+ //ScsiInitiatorIds int64
+ //SdcIds int64
+ //SecondaryReadFromDevBwc int64
+ //SecondaryReadFromRmcacheBwc int64
+ //SecondaryVacInKb int64
+ //SemiProtectedCapacityInKb int64
+ //SemiProtectedVacInKb int64
+ //SnapCapacityInUseOccupiedInKb int64
+ //UnusedCapacityInKb int64
+ }
+ SdcStatistics struct {
+ NumOfMappedVolumes int64
+ UserDataReadBwc Bwc
+ UserDataWriteBwc Bwc
+ //VolumeIds int64
+ }
+ StoragePoolStatistics struct {
+ CapacityStatistics
+
+ NumOfDevices int64
+ NumOfVolumes int64
+ NumOfVtrees int64
+ NumOfSnapshots int64
+
+ //SnapCapacityInUseInKb int64
+ //BackgroundScanCompareCount int64
+ //BackgroundScannedInMB int64
+ //ActiveBckRebuildCapacityInKb int64
+ //ActiveFwdRebuildCapacityInKb int64
+ //ActiveMovingCapacityInKb int64
+ //ActiveMovingInBckRebuildJobs int64
+ //ActiveMovingInFwdRebuildJobs int64
+ //ActiveMovingInNormRebuildJobs int64
+ //ActiveMovingInRebalanceJobs int64
+ //ActiveMovingOutBckRebuildJobs int64
+ //ActiveMovingOutFwdRebuildJobs int64
+ //ActiveMovingOutNormRebuildJobs int64
+ //ActiveMovingRebalanceJobs int64
+ //ActiveNormRebuildCapacityInKb int64
+ //ActiveRebalanceCapacityInKb int64
+ //AtRestCapacityInKb int64
+ //BckRebuildCapacityInKb int64
+ //BckRebuildReadBwc int64
+ //BckRebuildWriteBwc int64
+ //DegradedFailedVacInKb int64
+ //DegradedHealthyVacInKb int64
+ //DeviceIds int64
+ //FailedVacInKb int64
+ //FixedReadErrorCount int64
+ //FwdRebuildCapacityInKb int64
+ //FwdRebuildReadBwc int64
+ //FwdRebuildWriteBwc int64
+ //InMaintenanceVacInKb int64
+ //InUseVacInKb int64
+ //MovingCapacityInKb int64
+ //NormRebuildCapacityInKb int64
+ //NormRebuildReadBwc int64
+ //NormRebuildWriteBwc int64
+ //NumOfMappedToAllVolumes int64
+ //NumOfThickBaseVolumes int64
+ //NumOfThinBaseVolumes int64
+ //NumOfUnmappedVolumes int64
+ //NumOfVolumesInDeletion int64
+ //PendingBckRebuildCapacityInKb int64
+ //PendingFwdRebuildCapacityInKb int64
+ //PendingMovingCapacityInKb int64
+ //PendingMovingInBckRebuildJobs int64
+ //PendingMovingInFwdRebuildJobs int64
+ //PendingMovingInNormRebuildJobs int64
+ //PendingMovingInRebalanceJobs int64
+ //PendingMovingOutBckRebuildJobs int64
+ //PendingMovingOutFwdRebuildJobs int64
+ //PendingMovingOutNormrebuildJobs int64
+ //PendingMovingRebalanceJobs int64
+ //PendingNormRebuildCapacityInKb int64
+ //PendingRebalanceCapacityInKb int64
+ //PrimaryReadBwc int64
+ //PrimaryReadFromDevBwc int64
+ //PrimaryReadFromRmcacheBwc int64
+ //PrimaryVacInKb int64
+ //PrimaryWriteBwc int64
+ //ProtectedVacInKb int64
+ //RebalanceCapacityInKb int64
+ //RebalanceReadBwc int64
+ //RebalanceWriteBwc int64
+ //RfacheReadHit int64
+ //RfacheWriteHit int64
+ //RfcacheAvgReadTime int64
+ //RfcacheAvgWriteTime int64
+ //RfcacheIoErrors int64
+ //RfcacheIosOutstanding int64
+ //RfcacheIosSkipped int64
+ //RfcacheReadMiss int64
+ //RfcacheReadsFromCache int64
+ //RfcacheReadsPending int64
+ //RfcacheReadsReceived int64
+ //RfcacheReadsSkipped int64
+ //RfcacheReadsSkippedAlignedSizeTooLarge int64
+ //RfcacheReadsSkippedHeavyLoad int64
+ //RfcacheReadsSkippedInternalError int64
+ //RfcacheReadsSkippedLockIos int64
+ //RfcacheReadsSkippedLowResources int64
+ //RfcacheReadsSkippedMaxIoSize int64
+ //RfcacheReadsSkippedStuckIo int64
+ //RfcacheSkippedUnlinedWrite int64
+ //RfcacheSourceDeviceReads int64
+ //RfcacheSourceDeviceWrites int64
+ //RfcacheWriteMiss int64
+ //RfcacheWritePending int64
+ //RfcacheWritesReceived int64
+ //RfcacheWritesSkippedCacheMiss int64
+ //RfcacheWritesSkippedHeavyLoad int64
+ //RfcacheWritesSkippedInternalError int64
+ //RfcacheWritesSkippedLowResources int64
+ //RfcacheWritesSkippedMaxIoSize int64
+ //RfcacheWritesSkippedStuckIo int64
+ //RmPendingAllocatedInKb int64
+ //SecondaryReadBwc int64
+ //SecondaryReadFromDevBwc int64
+ //SecondaryReadFromRmcacheBwc int64
+ //SecondaryVacInKb int64
+ //SecondaryWriteBwc int64
+ //SemiProtectedCapacityInKb int64
+ //SemiProtectedVacInKb int64
+ //SnapCapacityInUseOccupiedInKb int64
+ //TotalReadBwc int64
+ //TotalWriteBwc int64
+ //UnusedCapacityInKb int64
+ //UserDataReadBwc int64
+ //UserDataWriteBwc int64
+ //VolumeIds int64
+ //VtreeIds int64
+ }
+ DeviceStatistic struct {
+ // BackgroundScanCompareCount int64
+ // BackgroundScannedInMB int64
+ // ActiveMovingInBckRebuildJobs int64
+ // ActiveMovingInFwdRebuildJobs int64
+ // ActiveMovingInNormRebuildJobs int64
+ // ActiveMovingInRebalanceJobs int64
+ // ActiveMovingOutBckRebuildJobs int64
+ // ActiveMovingOutFwdRebuildJobs int64
+ // ActiveMovingOutNormRebuildJobs int64
+ // ActiveMovingRebalanceJobs int64
+ // AvgReadLatencyInMicrosec int64
+ // AvgReadSizeInBytes int64
+ // AvgWriteLatencyInMicrosec int64
+ // AvgWriteSizeInBytes int64
+ // BckRebuildReadBwc int64
+ // BckRebuildWriteBwc int64
+ // CapacityInUseInKb int64
+ // CapacityLimitInKb int64
+ // DegradedFailedVacInKb int64
+ // DegradedHealthyVacInKb int64
+ // FailedVacInKb int64
+ // FixedReadErrorCount int64
+ // FwdRebuildReadBwc int64
+ // FwdRebuildWriteBwc int64
+ // InMaintenanceVacInKb int64
+ // InUseVacInKb int64
+ // MaxCapacityInKb int64
+ // NormRebuildReadBwc int64
+ // NormRebuildWriteBwc int64
+ // PendingMovingInBckRebuildJobs int64
+ // PendingMovingInFwdRebuildJobs int64
+ // PendingMovingInNormRebuildJobs int64
+ // PendingMovingInRebalanceJobs int64
+ // PendingMovingOutBckRebuildJobs int64
+ // PendingMovingOutFwdRebuildJobs int64
+ // PendingMovingOutNormrebuildJobs int64
+ // PendingMovingRebalanceJobs int64
+ // PrimaryReadBwc int64
+ // PrimaryReadFromDevBwc int64
+ // PrimaryReadFromRmcacheBwc int64
+ // PrimaryVacInKb int64
+ // PrimaryWriteBwc int64
+ // ProtectedVacInKb int64
+ // RebalanceReadBwc int64
+ // RebalanceWriteBwc int64
+ // RfacheReadHit int64
+ // RfacheWriteHit int64
+ // RfcacheAvgReadTime int64
+ // RfcacheAvgWriteTime int64
+ // RfcacheIoErrors int64
+ // RfcacheIosOutstanding int64
+ // RfcacheIosSkipped int64
+ // RfcacheReadMiss int64
+ // RfcacheReadsFromCache int64
+ // RfcacheReadsPending int64
+ // RfcacheReadsReceived int64
+ // RfcacheReadsSkipped int64
+ // RfcacheReadsSkippedAlignedSizeTooLarge int64
+ // RfcacheReadsSkippedHeavyLoad int64
+ // RfcacheReadsSkippedInternalError int64
+ // RfcacheReadsSkippedLockIos int64
+ // RfcacheReadsSkippedLowResources int64
+ // RfcacheReadsSkippedMaxIoSize int64
+ // RfcacheReadsSkippedStuckIo int64
+ // RfcacheSkippedUnlinedWrite int64
+ // RfcacheSourceDeviceReads int64
+ // RfcacheSourceDeviceWrites int64
+ // RfcacheWriteMiss int64
+ // RfcacheWritePending int64
+ // RfcacheWritesReceived int64
+ // RfcacheWritesSkippedCacheMiss int64
+ // RfcacheWritesSkippedHeavyLoad int64
+ // RfcacheWritesSkippedInternalError int64
+ // RfcacheWritesSkippedLowResources int64
+ // RfcacheWritesSkippedMaxIoSize int64
+ // RfcacheWritesSkippedStuckIo int64
+ // RmPendingAllocatedInKb int64
+ // SecondaryReadBwc int64
+ // SecondaryReadFromDevBwc int64
+ // SecondaryReadFromRmcacheBwc int64
+ // SecondaryVacInKb int64
+ // SecondaryWriteBwc int64
+ // SemiProtectedVacInKb int64
+ // SnapCapacityInUseInKb int64
+ // SnapCapacityInUseOccupiedInKb int64
+ // ThickCapacityInUseInKb int64
+ // ThinCapacityAllocatedInKb int64
+ // ThinCapacityInUseInKb int64
+ // TotalReadBwc int64
+ // TotalWriteBwc int64
+ // UnreachableUnusedCapacityInKb int64
+ // UnusedCapacityInKb int64
+ }
+ FaultSetStatistics struct {
+ // BackgroundScanCompareCount int64
+ // BackgroundScannedInMB int64
+ // ActiveMovingInBckRebuildJobs int64
+ // ActiveMovingInFwdRebuildJobs int64
+ // ActiveMovingInNormRebuildJobs int64
+ // ActiveMovingInRebalanceJobs int64
+ // ActiveMovingOutBckRebuildJobs int64
+ // ActiveMovingOutFwdRebuildJobs int64
+ // ActiveMovingOutNormRebuildJobs int64
+ // ActiveMovingRebalanceJobs int64
+ // BckRebuildReadBwc int64
+ // BckRebuildWriteBwc int64
+ // CapacityInUseInKb int64
+ // CapacityLimitInKb int64
+ // DegradedFailedVacInKb int64
+ // DegradedHealthyVacInKb int64
+ // FailedVacInKb int64
+ // FixedReadErrorCount int64
+ // FwdRebuildReadBwc int64
+ // FwdRebuildWriteBwc int64
+ // InMaintenanceVacInKb int64
+ // InUseVacInKb int64
+ // MaxCapacityInKb int64
+ // NormRebuildReadBwc int64
+ // NormRebuildWriteBwc int64
+ // NumOfSds int64
+ // PendingMovingInBckRebuildJobs int64
+ // PendingMovingInFwdRebuildJobs int64
+ // PendingMovingInNormRebuildJobs int64
+ // PendingMovingInRebalanceJobs int64
+ // PendingMovingOutBckRebuildJobs int64
+ // PendingMovingOutFwdRebuildJobs int64
+ // PendingMovingOutNormrebuildJobs int64
+ // PendingMovingRebalanceJobs int64
+ // PrimaryReadBwc int64
+ // PrimaryReadFromDevBwc int64
+ // PrimaryReadFromRmcacheBwc int64
+ // PrimaryVacInKb int64
+ // PrimaryWriteBwc int64
+ // ProtectedVacInKb int64
+ // RebalancePerReceiveJobNetThrottlingInKbps int64
+ // RebalanceReadBwc int64
+ // RebalanceWaitSendQLength int64
+ // RebalanceWriteBwc int64
+ // RebuildPerReceiveJobNetThrottlingInKbps int64
+ // RebuildWaitSendQLength int64
+ // RfacheReadHit int64
+ // RfacheWriteHit int64
+ // RfcacheAvgReadTime int64
+ // RfcacheAvgWriteTime int64
+ // RfcacheFdAvgReadTime int64
+ // RfcacheFdAvgWriteTime int64
+ // RfcacheFdCacheOverloaded int64
+ // RfcacheFdInlightReads int64
+ // RfcacheFdInlightWrites int64
+ // RfcacheFdIoErrors int64
+ // RfcacheFdMonitorErrorStuckIo int64
+ // RfcacheFdReadTimeGreater1Min int64
+ // RfcacheFdReadTimeGreater1Sec int64
+ // RfcacheFdReadTimeGreater500Millis int64
+ // RfcacheFdReadTimeGreater5Sec int64
+ // RfcacheFdReadsReceived int64
+ // RfcacheFdWriteTimeGreater1Min int64
+ // RfcacheFdWriteTimeGreater1Sec int64
+ // RfcacheFdWriteTimeGreater500Millis int64
+ // RfcacheFdWriteTimeGreater5Sec int64
+ // RfcacheFdWritesReceived int64
+ // RfcacheIoErrors int64
+ // RfcacheIosOutstanding int64
+ // RfcacheIosSkipped int64
+ // RfcachePooIosOutstanding int64
+ // RfcachePoolCachePages int64
+ // RfcachePoolEvictions int64
+ // RfcachePoolInLowMemoryCondition int64
+ // RfcachePoolIoTimeGreater1Min int64
+ // RfcachePoolLockTimeGreater1Sec int64
+ // RfcachePoolLowResourcesInitiatedPassthroughMode int64
+ // RfcachePoolNumCacheDevs int64
+ // RfcachePoolNumSrcDevs int64
+ // RfcachePoolPagesInuse int64
+ // RfcachePoolReadHit int64
+ // RfcachePoolReadMiss int64
+ // RfcachePoolReadPendingG10Millis int64
+ // RfcachePoolReadPendingG1Millis int64
+ // RfcachePoolReadPendingG1Sec int64
+ // RfcachePoolReadPendingG500Micro int64
+ // RfcachePoolReadsPending int64
+ // RfcachePoolSize int64
+ // RfcachePoolSourceIdMismatch int64
+ // RfcachePoolSuspendedIos int64
+ // RfcachePoolSuspendedPequestsRedundantSearchs int64
+ // RfcachePoolWriteHit int64
+ // RfcachePoolWriteMiss int64
+ // RfcachePoolWritePending int64
+ // RfcachePoolWritePendingG10Millis int64
+ // RfcachePoolWritePendingG1Millis int64
+ // RfcachePoolWritePendingG1Sec int64
+ // RfcachePoolWritePendingG500Micro int64
+ // RfcacheReadMiss int64
+ // RfcacheReadsFromCache int64
+ // RfcacheReadsPending int64
+ // RfcacheReadsReceived int64
+ // RfcacheReadsSkipped int64
+ // RfcacheReadsSkippedAlignedSizeTooLarge int64
+ // RfcacheReadsSkippedHeavyLoad int64
+ // RfcacheReadsSkippedInternalError int64
+ // RfcacheReadsSkippedLockIos int64
+ // RfcacheReadsSkippedLowResources int64
+ // RfcacheReadsSkippedMaxIoSize int64
+ // RfcacheReadsSkippedStuckIo int64
+ // RfcacheSkippedUnlinedWrite int64
+ // RfcacheSourceDeviceReads int64
+ // RfcacheSourceDeviceWrites int64
+ // RfcacheWriteMiss int64
+ // RfcacheWritePending int64
+ // RfcacheWritesReceived int64
+ // RfcacheWritesSkippedCacheMiss int64
+ // RfcacheWritesSkippedHeavyLoad int64
+ // RfcacheWritesSkippedInternalError int64
+ // RfcacheWritesSkippedLowResources int64
+ // RfcacheWritesSkippedMaxIoSize int64
+ // RfcacheWritesSkippedStuckIo int64
+ // RmPendingAllocatedInKb int64
+ // Rmcache128kbEntryCount int64
+ // Rmcache16kbEntryCount int64
+ // Rmcache32kbEntryCount int64
+ // Rmcache4kbEntryCount int64
+ // Rmcache64kbEntryCount int64
+ // Rmcache8kbEntryCount int64
+ // RmcacheBigBlockEvictionCount int64
+ // RmcacheBigBlockEvictionSizeCountInKb int64
+ // RmcacheCurrNumOf128kbEntries int64
+ // RmcacheCurrNumOf16kbEntries int64
+ // RmcacheCurrNumOf32kbEntries int64
+ // RmcacheCurrNumOf4kbEntries int64
+ // RmcacheCurrNumOf64kbEntries int64
+ // RmcacheCurrNumOf8kbEntries int64
+ // RmcacheEntryEvictionCount int64
+ // RmcacheEntryEvictionSizeCountInKb int64
+ // RmcacheNoEvictionCount int64
+ // RmcacheSizeInKb int64
+ // RmcacheSizeInUseInKb int64
+ // RmcacheSkipCountCacheAllBusy int64
+ // RmcacheSkipCountLargeIo int64
+ // RmcacheSkipCountUnaligned4kbIo int64
+ // SdsIds int64
+ // SecondaryReadBwc int64
+ // SecondaryReadFromDevBwc int64
+ // SecondaryReadFromRmcacheBwc int64
+ // SecondaryVacInKb int64
+ // SecondaryWriteBwc int64
+ // SemiProtectedVacInKb int64
+ // SnapCapacityInUseInKb int64
+ // SnapCapacityInUseOccupiedInKb int64
+ // ThickCapacityInUseInKb int64
+ // ThinCapacityAllocatedInKb int64
+ // ThinCapacityInUseInKb int64
+ // TotalReadBwc int64
+ // TotalWriteBwc int64
+ // UnreachableUnusedCapacityInKb int64
+ // UnusedCapacityInKb int64
+ }
+ ProtectionDomainStatistics struct {
+ // BackgroundScanCompareCount int64
+ // BackgroundScannedInMB int64
+ // ActiveBckRebuildCapacityInKb int64
+ // ActiveFwdRebuildCapacityInKb int64
+ // ActiveMovingCapacityInKb int64
+ // ActiveMovingInBckRebuildJobs int64
+ // ActiveMovingInFwdRebuildJobs int64
+ // ActiveMovingInNormRebuildJobs int64
+ // ActiveMovingInRebalanceJobs int64
+ // ActiveMovingOutBckRebuildJobs int64
+ // ActiveMovingOutFwdRebuildJobs int64
+ // ActiveMovingOutNormRebuildJobs int64
+ // ActiveMovingRebalanceJobs int64
+ // ActiveNormRebuildCapacityInKb int64
+ // ActiveRebalanceCapacityInKb int64
+ // AtRestCapacityInKb int64
+ // BckRebuildCapacityInKb int64
+ // BckRebuildReadBwc int64
+ // BckRebuildWriteBwc int64
+ // CapacityAvailableForVolumeAllocationInKb int64
+ // CapacityInUseInKb int64
+ // CapacityLimitInKb int64
+ // DegradedFailedCapacityInKb int64
+ // DegradedFailedVacInKb int64
+ // DegradedHealthyCapacityInKb int64
+ // DegradedHealthyVacInKb int64
+ // FailedCapacityInKb int64
+ // FailedVacInKb int64
+ // FaultSetIds int64
+ // FixedReadErrorCount int64
+ // FwdRebuildCapacityInKb int64
+ // FwdRebuildReadBwc int64
+ // FwdRebuildWriteBwc int64
+ // InMaintenanceCapacityInKb int64
+ // InMaintenanceVacInKb int64
+ // InUseVacInKb int64
+ // MaxCapacityInKb int64
+ // MovingCapacityInKb int64
+ // NormRebuildCapacityInKb int64
+ // NormRebuildReadBwc int64
+ // NormRebuildWriteBwc int64
+ // NumOfFaultSets int64
+ // NumOfMappedToAllVolumes int64
+ // NumOfSds int64
+ // NumOfSnapshots int64
+ // NumOfStoragePools int64
+ // NumOfThickBaseVolumes int64
+ // NumOfThinBaseVolumes int64
+ // NumOfUnmappedVolumes int64
+ // NumOfVolumesInDeletion int64
+ // PendingBckRebuildCapacityInKb int64
+ // PendingFwdRebuildCapacityInKb int64
+ // PendingMovingCapacityInKb int64
+ // PendingMovingInBckRebuildJobs int64
+ // PendingMovingInFwdRebuildJobs int64
+ // PendingMovingInNormRebuildJobs int64
+ // PendingMovingInRebalanceJobs int64
+ // PendingMovingOutBckRebuildJobs int64
+ // PendingMovingOutFwdRebuildJobs int64
+ // PendingMovingOutNormrebuildJobs int64
+ // PendingMovingRebalanceJobs int64
+ // PendingNormRebuildCapacityInKb int64
+ // PendingRebalanceCapacityInKb int64
+ // PrimaryReadBwc int64
+ // PrimaryReadFromDevBwc int64
+ // PrimaryReadFromRmcacheBwc int64
+ // PrimaryVacInKb int64
+ // PrimaryWriteBwc int64
+ // ProtectedCapacityInKb int64
+ // ProtectedVacInKb int64
+ // RebalanceCapacityInKb int64
+ // RebalancePerReceiveJobNetThrottlingInKbps int64
+ // RebalanceReadBwc int64
+ // RebalanceWaitSendQLength int64
+ // RebalanceWriteBwc int64
+ // RebuildPerReceiveJobNetThrottlingInKbps int64
+ // RebuildWaitSendQLength int64
+ // RfacheReadHit int64
+ // RfacheWriteHit int64
+ // RfcacheAvgReadTime int64
+ // RfcacheAvgWriteTime int64
+ // RfcacheFdAvgReadTime int64
+ // RfcacheFdAvgWriteTime int64
+ // RfcacheFdCacheOverloaded int64
+ // RfcacheFdInlightReads int64
+ // RfcacheFdInlightWrites int64
+ // RfcacheFdIoErrors int64
+ // RfcacheFdMonitorErrorStuckIo int64
+ // RfcacheFdReadTimeGreater1Min int64
+ // RfcacheFdReadTimeGreater1Sec int64
+ // RfcacheFdReadTimeGreater500Millis int64
+ // RfcacheFdReadTimeGreater5Sec int64
+ // RfcacheFdReadsReceived int64
+ // RfcacheFdWriteTimeGreater1Min int64
+ // RfcacheFdWriteTimeGreater1Sec int64
+ // RfcacheFdWriteTimeGreater500Millis int64
+ // RfcacheFdWriteTimeGreater5Sec int64
+ // RfcacheFdWritesReceived int64
+ // RfcacheIoErrors int64
+ // RfcacheIosOutstanding int64
+ // RfcacheIosSkipped int64
+ // RfcachePooIosOutstanding int64
+ // RfcachePoolCachePages int64
+ // RfcachePoolEvictions int64
+ // RfcachePoolInLowMemoryCondition int64
+ // RfcachePoolIoTimeGreater1Min int64
+ // RfcachePoolLockTimeGreater1Sec int64
+ // RfcachePoolLowResourcesInitiatedPassthroughMode int64
+ // RfcachePoolNumCacheDevs int64
+ // RfcachePoolNumSrcDevs int64
+ // RfcachePoolPagesInuse int64
+ // RfcachePoolReadHit int64
+ // RfcachePoolReadMiss int64
+ // RfcachePoolReadPendingG10Millis int64
+ // RfcachePoolReadPendingG1Millis int64
+ // RfcachePoolReadPendingG1Sec int64
+ // RfcachePoolReadPendingG500Micro int64
+ // RfcachePoolReadsPending int64
+ // RfcachePoolSize int64
+ // RfcachePoolSourceIdMismatch int64
+ // RfcachePoolSuspendedIos int64
+ // RfcachePoolSuspendedPequestsRedundantSearchs int64
+ // RfcachePoolWriteHit int64
+ // RfcachePoolWriteMiss int64
+ // RfcachePoolWritePending int64
+ // RfcachePoolWritePendingG10Millis int64
+ // RfcachePoolWritePendingG1Millis int64
+ // RfcachePoolWritePendingG1Sec int64
+ // RfcachePoolWritePendingG500Micro int64
+ // RfcacheReadMiss int64
+ // RfcacheReadsFromCache int64
+ // RfcacheReadsPending int64
+ // RfcacheReadsReceived int64
+ // RfcacheReadsSkipped int64
+ // RfcacheReadsSkippedAlignedSizeTooLarge int64
+ // RfcacheReadsSkippedHeavyLoad int64
+ // RfcacheReadsSkippedInternalError int64
+ // RfcacheReadsSkippedLockIos int64
+ // RfcacheReadsSkippedLowResources int64
+ // RfcacheReadsSkippedMaxIoSize int64
+ // RfcacheReadsSkippedStuckIo int64
+ // RfcacheSkippedUnlinedWrite int64
+ // RfcacheSourceDeviceReads int64
+ // RfcacheSourceDeviceWrites int64
+ // RfcacheWriteMiss int64
+ // RfcacheWritePending int64
+ // RfcacheWritesReceived int64
+ // RfcacheWritesSkippedCacheMiss int64
+ // RfcacheWritesSkippedHeavyLoad int64
+ // RfcacheWritesSkippedInternalError int64
+ // RfcacheWritesSkippedLowResources int64
+ // RfcacheWritesSkippedMaxIoSize int64
+ // RfcacheWritesSkippedStuckIo int64
+ // RmPendingAllocatedInKb int64
+ // Rmcache128kbEntryCount int64
+ // Rmcache16kbEntryCount int64
+ // Rmcache32kbEntryCount int64
+ // Rmcache4kbEntryCount int64
+ // Rmcache64kbEntryCount int64
+ // Rmcache8kbEntryCount int64
+ // RmcacheBigBlockEvictionCount int64
+ // RmcacheBigBlockEvictionSizeCountInKb int64
+ // RmcacheCurrNumOf128kbEntries int64
+ // RmcacheCurrNumOf16kbEntries int64
+ // RmcacheCurrNumOf32kbEntries int64
+ // RmcacheCurrNumOf4kbEntries int64
+ // RmcacheCurrNumOf64kbEntries int64
+ // RmcacheCurrNumOf8kbEntries int64
+ // RmcacheEntryEvictionCount int64
+ // RmcacheEntryEvictionSizeCountInKb int64
+ // RmcacheNoEvictionCount int64
+ // RmcacheSizeInKb int64
+ // RmcacheSizeInUseInKb int64
+ // RmcacheSkipCountCacheAllBusy int64
+ // RmcacheSkipCountLargeIo int64
+ // RmcacheSkipCountUnaligned4kbIo int64
+ // SdsIds int64
+ // SecondaryReadBwc int64
+ // SecondaryReadFromDevBwc int64
+ // SecondaryReadFromRmcacheBwc int64
+ // SecondaryVacInKb int64
+ // SecondaryWriteBwc int64
+ // SemiProtectedCapacityInKb int64
+ // SemiProtectedVacInKb int64
+ // SnapCapacityInUseInKb int64
+ // SnapCapacityInUseOccupiedInKb int64
+ // SpareCapacityInKb int64
+ // StoragePoolIds int64
+ // ThickCapacityInUseInKb int64
+ // ThinCapacityAllocatedInKb int64
+ // ThinCapacityInUseInKb int64
+ // TotalReadBwc int64
+ // TotalWriteBwc int64
+ // UnreachableUnusedCapacityInKb int64
+ // UnusedCapacityInKb int64
+ // UserDataReadBwc int64
+ // UserDataWriteBwc int64
+ }
+ RFCacheDeviceStatistics struct {
+ // RfcacheFdAvgReadTime int64
+ // RfcacheFdAvgWriteTime int64
+ // RfcacheFdCacheOverloaded int64
+ // RfcacheFdInlightReads int64
+ // RfcacheFdInlightWrites int64
+ // RfcacheFdIoErrors int64
+ // RfcacheFdMonitorErrorStuckIo int64
+ // RfcacheFdReadTimeGreater1Min int64
+ // RfcacheFdReadTimeGreater1Sec int64
+ // RfcacheFdReadTimeGreater500Millis int64
+ // RfcacheFdReadTimeGreater5Sec int64
+ // RfcacheFdReadsReceived int64
+ // RfcacheFdWriteTimeGreater1Min int64
+ // RfcacheFdWriteTimeGreater1Sec int64
+ // RfcacheFdWriteTimeGreater500Millis int64
+ // RfcacheFdWriteTimeGreater5Sec int64
+ // RfcacheFdWritesReceived int64
+ }
+ SdsStatistics struct {
+ // BackgroundScanCompareCount int64
+ // BackgroundScannedInMB int64
+ // ActiveMovingInBckRebuildJobs int64
+ // ActiveMovingInFwdRebuildJobs int64
+ // ActiveMovingInNormRebuildJobs int64
+ // ActiveMovingInRebalanceJobs int64
+ // ActiveMovingOutBckRebuildJobs int64
+ // ActiveMovingOutFwdRebuildJobs int64
+ // ActiveMovingOutNormRebuildJobs int64
+ // ActiveMovingRebalanceJobs int64
+ // BckRebuildReadBwc int64
+ // BckRebuildWriteBwc int64
+ // CapacityInUseInKb int64
+ // CapacityLimitInKb int64
+ // DegradedFailedVacInKb int64
+ // DegradedHealthyVacInKb int64
+ // DeviceIds int64
+ // FailedVacInKb int64
+ // FixedReadErrorCount int64
+ // FwdRebuildReadBwc int64
+ // FwdRebuildWriteBwc int64
+ // InMaintenanceVacInKb int64
+ // InUseVacInKb int64
+ // MaxCapacityInKb int64
+ // NormRebuildReadBwc int64
+ // NormRebuildWriteBwc int64
+ // NumOfDevices int64
+ // NumOfRfcacheDevices int64
+ // PendingMovingInBckRebuildJobs int64
+ // PendingMovingInFwdRebuildJobs int64
+ // PendingMovingInNormRebuildJobs int64
+ // PendingMovingInRebalanceJobs int64
+ // PendingMovingOutBckRebuildJobs int64
+ // PendingMovingOutFwdRebuildJobs int64
+ // PendingMovingOutNormrebuildJobs int64
+ // PendingMovingRebalanceJobs int64
+ // PrimaryReadBwc int64
+ // PrimaryReadFromDevBwc int64
+ // PrimaryReadFromRmcacheBwc int64
+ // PrimaryVacInKb int64
+ // PrimaryWriteBwc int64
+ // ProtectedVacInKb int64
+ // RebalancePerReceiveJobNetThrottlingInKbps int64
+ // RebalanceReadBwc int64
+ // RebalanceWaitSendQLength int64
+ // RebalanceWriteBwc int64
+ // RebuildPerReceiveJobNetThrottlingInKbps int64
+ // RebuildWaitSendQLength int64
+ // RfacheReadHit int64
+ // RfacheWriteHit int64
+ // RfcacheAvgReadTime int64
+ // RfcacheAvgWriteTime int64
+ // RfcacheDeviceIds int64
+ // RfcacheFdAvgReadTime int64
+ // RfcacheFdAvgWriteTime int64
+ // RfcacheFdCacheOverloaded int64
+ // RfcacheFdInlightReads int64
+ // RfcacheFdInlightWrites int64
+ // RfcacheFdIoErrors int64
+ // RfcacheFdMonitorErrorStuckIo int64
+ // RfcacheFdReadTimeGreater1Min int64
+ // RfcacheFdReadTimeGreater1Sec int64
+ // RfcacheFdReadTimeGreater500Millis int64
+ // RfcacheFdReadTimeGreater5Sec int64
+ // RfcacheFdReadsReceived int64
+ // RfcacheFdWriteTimeGreater1Min int64
+ // RfcacheFdWriteTimeGreater1Sec int64
+ // RfcacheFdWriteTimeGreater500Millis int64
+ // RfcacheFdWriteTimeGreater5Sec int64
+ // RfcacheFdWritesReceived int64
+ // RfcacheIoErrors int64
+ // RfcacheIosOutstanding int64
+ // RfcacheIosSkipped int64
+ // RfcachePooIosOutstanding int64
+ // RfcachePoolCachePages int64
+ // RfcachePoolContinuosMem int64
+ // RfcachePoolEvictions int64
+ // RfcachePoolInLowMemoryCondition int64
+ // RfcachePoolIoTimeGreater1Min int64
+ // RfcachePoolLockTimeGreater1Sec int64
+ // RfcachePoolLowResourcesInitiatedPassthroughMode int64
+ // RfcachePoolMaxIoSize int64
+ // RfcachePoolNumCacheDevs int64
+ // RfcachePoolNumOfDriverTheads int64
+ // RfcachePoolNumSrcDevs int64
+ // RfcachePoolOpmode int64
+ // RfcachePoolPageSize int64
+ // RfcachePoolPagesInuse int64
+ // RfcachePoolReadHit int64
+ // RfcachePoolReadMiss int64
+ // RfcachePoolReadPendingG10Millis int64
+ // RfcachePoolReadPendingG1Millis int64
+ // RfcachePoolReadPendingG1Sec int64
+ // RfcachePoolReadPendingG500Micro int64
+ // RfcachePoolReadsPending int64
+ // RfcachePoolSize int64
+ // RfcachePoolSourceIdMismatch int64
+ // RfcachePoolSuspendedIos int64
+ // RfcachePoolSuspendedIosMax int64
+ // RfcachePoolSuspendedPequestsRedundantSearchs int64
+ // RfcachePoolWriteHit int64
+ // RfcachePoolWriteMiss int64
+ // RfcachePoolWritePending int64
+ // RfcachePoolWritePendingG10Millis int64
+ // RfcachePoolWritePendingG1Millis int64
+ // RfcachePoolWritePendingG1Sec int64
+ // RfcachePoolWritePendingG500Micro int64
+ // RfcacheReadMiss int64
+ // RfcacheReadsFromCache int64
+ // RfcacheReadsPending int64
+ // RfcacheReadsReceived int64
+ // RfcacheReadsSkipped int64
+ // RfcacheReadsSkippedAlignedSizeTooLarge int64
+ // RfcacheReadsSkippedHeavyLoad int64
+ // RfcacheReadsSkippedInternalError int64
+ // RfcacheReadsSkippedLockIos int64
+ // RfcacheReadsSkippedLowResources int64
+ // RfcacheReadsSkippedMaxIoSize int64
+ // RfcacheReadsSkippedStuckIo int64
+ // RfcacheSkippedUnlinedWrite int64
+ // RfcacheSourceDeviceReads int64
+ // RfcacheSourceDeviceWrites int64
+ // RfcacheWriteMiss int64
+ // RfcacheWritePending int64
+ // RfcacheWritesReceived int64
+ // RfcacheWritesSkippedCacheMiss int64
+ // RfcacheWritesSkippedHeavyLoad int64
+ // RfcacheWritesSkippedInternalError int64
+ // RfcacheWritesSkippedLowResources int64
+ // RfcacheWritesSkippedMaxIoSize int64
+ // RfcacheWritesSkippedStuckIo int64
+ // RmPendingAllocatedInKb int64
+ // Rmcache128kbEntryCount int64
+ // Rmcache16kbEntryCount int64
+ // Rmcache32kbEntryCount int64
+ // Rmcache4kbEntryCount int64
+ // Rmcache64kbEntryCount int64
+ // Rmcache8kbEntryCount int64
+ // RmcacheBigBlockEvictionCount int64
+ // RmcacheBigBlockEvictionSizeCountInKb int64
+ // RmcacheCurrNumOf128kbEntries int64
+ // RmcacheCurrNumOf16kbEntries int64
+ // RmcacheCurrNumOf32kbEntries int64
+ // RmcacheCurrNumOf4kbEntries int64
+ // RmcacheCurrNumOf64kbEntries int64
+ // RmcacheCurrNumOf8kbEntries int64
+ // RmcacheEntryEvictionCount int64
+ // RmcacheEntryEvictionSizeCountInKb int64
+ // RmcacheNoEvictionCount int64
+ // RmcacheSizeInKb int64
+ // RmcacheSizeInUseInKb int64
+ // RmcacheSkipCountCacheAllBusy int64
+ // RmcacheSkipCountLargeIo int64
+ // RmcacheSkipCountUnaligned4kbIo int64
+ // SecondaryReadBwc int64
+ // SecondaryReadFromDevBwc int64
+ // SecondaryReadFromRmcacheBwc int64
+ // SecondaryVacInKb int64
+ // SecondaryWriteBwc int64
+ // SemiProtectedVacInKb int64
+ // SnapCapacityInUseInKb int64
+ // SnapCapacityInUseOccupiedInKb int64
+ // ThickCapacityInUseInKb int64
+ // ThinCapacityAllocatedInKb int64
+ // ThinCapacityInUseInKb int64
+ // TotalReadBwc int64
+ // TotalWriteBwc int64
+ // UnreachableUnusedCapacityInKb int64
+ // UnusedCapacityInKb int64
+ }
+ VolumeStatistics struct {
+ // ChildVolumeIds int64
+ // DescendantVolumeIds int64
+ // MappedSdcIds int64
+ // NumOfChildVolumes int64
+ // NumOfDescendantVolumes int64
+ // NumOfMappedScsiInitiators int64
+ // NumOfMappedSdcs int64
+ // UserDataReadBwc int64
+ // UserDataWriteBwc int64
+ }
+ VTreeStatistics struct {
+ // BaseNetCapacityInUseInKb int64
+ // NetCapacityInUseInKb int64
+ // NumOfVolumes int64
+ // SnapNetCapacityInUseInKb int64
+ // TrimmedCapacityInKb int64
+ // VolumeIds int64
+ }
+)
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/collect.go b/src/go/collectors/go.d.plugin/modules/scaleio/collect.go
new file mode 100644
index 000000000..93a0a609d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/collect.go
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import (
+ "time"
+
+ "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/stm"
+)
+
+const discoveryEvery = 5
+
+func (s *ScaleIO) collect() (map[string]int64, error) {
+ s.runs += 1
+ if !s.lastDiscoveryOK || s.runs%discoveryEvery == 0 {
+ if err := s.discovery(); err != nil {
+ return nil, err
+ }
+ }
+
+ stats, err := s.client.SelectedStatistics(query)
+ if err != nil {
+ return nil, err
+ }
+
+ mx := metrics{
+ System: s.collectSystem(stats.System),
+ StoragePool: s.collectStoragePool(stats.StoragePool),
+ Sdc: s.collectSdc(stats.Sdc),
+ }
+
+ s.updateCharts()
+ return stm.ToMap(mx), nil
+}
+
+func (s *ScaleIO) discovery() error {
+ start := time.Now()
+ s.Debugf("starting discovery")
+ ins, err := s.client.Instances()
+ if err != nil {
+ s.lastDiscoveryOK = false
+ return err
+ }
+ s.Debugf("discovering: discovered %d storage pools, %d sdcs, it took %s",
+ len(ins.StoragePoolList), len(ins.SdcList), time.Since(start))
+
+ s.discovered.pool = make(map[string]client.StoragePool, len(ins.StoragePoolList))
+ for _, pool := range ins.StoragePoolList {
+ s.discovered.pool[pool.ID] = pool
+ }
+ s.discovered.sdc = make(map[string]client.Sdc, len(ins.SdcList))
+ for _, sdc := range ins.SdcList {
+ s.discovered.sdc[sdc.ID] = sdc
+ }
+ s.lastDiscoveryOK = true
+ return nil
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/collect_sdc.go b/src/go/collectors/go.d.plugin/modules/scaleio/collect_sdc.go
new file mode 100644
index 000000000..e840b781d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/collect_sdc.go
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+func (s *ScaleIO) collectSdc(ss map[string]client.SdcStatistics) map[string]sdcMetrics {
+ ms := make(map[string]sdcMetrics, len(ss))
+
+ for id, stats := range ss {
+ sdc, ok := s.discovered.sdc[id]
+ if !ok {
+ continue
+ }
+ var m sdcMetrics
+ m.BW.set(
+ calcBW(stats.UserDataReadBwc),
+ calcBW(stats.UserDataWriteBwc),
+ )
+ m.IOPS.set(
+ calcIOPS(stats.UserDataReadBwc),
+ calcIOPS(stats.UserDataWriteBwc),
+ )
+ m.IOSize.set(
+ calcIOSize(stats.UserDataReadBwc),
+ calcIOSize(stats.UserDataWriteBwc),
+ )
+ m.MappedVolumes = stats.NumOfMappedVolumes
+ m.MDMConnectionState = isSdcConnected(sdc.MdmConnectionState)
+
+ ms[id] = m
+ }
+ return ms
+}
+
+func isSdcConnected(state string) bool {
+ return state == "Connected"
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/collect_storage_pool.go b/src/go/collectors/go.d.plugin/modules/scaleio/collect_storage_pool.go
new file mode 100644
index 000000000..409be0bdb
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/collect_storage_pool.go
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+func (s *ScaleIO) collectStoragePool(ss map[string]client.StoragePoolStatistics) map[string]storagePoolMetrics {
+ ms := make(map[string]storagePoolMetrics, len(ss))
+
+ for id, stats := range ss {
+ pool, ok := s.discovered.pool[id]
+ if !ok {
+ continue
+ }
+ var pm storagePoolMetrics
+ collectStoragePoolCapacity(&pm, stats, pool)
+ collectStoragePoolComponents(&pm, stats)
+
+ ms[id] = pm
+ }
+ return ms
+}
+
+func collectStoragePoolCapacity(pm *storagePoolMetrics, ps client.StoragePoolStatistics, pool client.StoragePool) {
+ collectCapacity(&pm.Capacity.capacity, ps.CapacityStatistics)
+ pm.Capacity.Utilization = calcCapacityUtilization(ps.CapacityInUseInKb, ps.MaxCapacityInKb, pool.SparePercentage)
+ pm.Capacity.AlertThreshold.Critical = pool.CapacityAlertCriticalThreshold
+ pm.Capacity.AlertThreshold.High = pool.CapacityAlertHighThreshold
+}
+
+func collectStoragePoolComponents(pm *storagePoolMetrics, ps client.StoragePoolStatistics) {
+ pm.Components.Devices = ps.NumOfDevices
+ pm.Components.Snapshots = ps.NumOfSnapshots
+ pm.Components.Volumes = ps.NumOfVolumes
+ pm.Components.Vtrees = ps.NumOfVtrees
+}
+
+func calcCapacityUtilization(inUse int64, max int64, sparePercent int64) float64 {
+ spare := float64(max) / 100 * float64(sparePercent)
+ return divFloat(float64(100*inUse), float64(max)-spare)
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/collect_system.go b/src/go/collectors/go.d.plugin/modules/scaleio/collect_system.go
new file mode 100644
index 000000000..b2c02db1b
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/collect_system.go
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+func (s *ScaleIO) collectSystem(ss client.SystemStatistics) systemMetrics {
+ var sm systemMetrics
+ collectSystemCapacity(&sm, ss)
+ collectSystemWorkload(&sm, ss)
+ collectSystemRebalance(&sm, ss)
+ collectSystemRebuild(&sm, ss)
+ collectSystemComponents(&sm, ss)
+ return sm
+}
+
+func collectSystemCapacity(sm *systemMetrics, ss client.SystemStatistics) {
+ collectCapacity(&sm.Capacity, ss.CapacityStatistics)
+}
+
+func collectCapacity(m *capacity, ss client.CapacityStatistics) {
+ // Health
+ m.Protected = ss.ProtectedCapacityInKb
+ m.InMaintenance = ss.InMaintenanceCapacityInKb
+ m.Degraded = sum(ss.DegradedFailedCapacityInKb, ss.DegradedHealthyCapacityInKb)
+ m.Failed = ss.FailedCapacityInKb
+ m.UnreachableUnused = ss.UnreachableUnusedCapacityInKb
+
+ // Capacity
+ m.MaxCapacity = ss.MaxCapacityInKb
+ m.ThickInUse = ss.ThickCapacityInUseInKb
+ m.ThinInUse = ss.ThinCapacityInUseInKb
+ m.Snapshot = ss.SnapCapacityInUseOccupiedInKb
+ m.Spare = ss.SpareCapacityInKb
+ m.Decreased = sum(ss.MaxCapacityInKb, -ss.CapacityLimitInKb) // TODO: probably wrong
+ // Note: can't use 'UnusedCapacityInKb' directly, dashboard shows calculated value
+ used := sum(
+ ss.ProtectedCapacityInKb,
+ ss.InMaintenanceCapacityInKb,
+ m.Decreased,
+ m.Degraded,
+ ss.FailedCapacityInKb,
+ ss.SpareCapacityInKb,
+ ss.UnreachableUnusedCapacityInKb,
+ ss.SnapCapacityInUseOccupiedInKb,
+ )
+ m.Unused = sum(ss.MaxCapacityInKb, -used)
+
+ // Other
+ m.InUse = ss.CapacityInUseInKb
+ m.AvailableForVolumeAllocation = ss.CapacityAvailableForVolumeAllocationInKb
+}
+
+func collectSystemComponents(sm *systemMetrics, ss client.SystemStatistics) {
+ m := &sm.Components
+
+ m.Devices = ss.NumOfDevices
+ m.FaultSets = ss.NumOfFaultSets
+ m.MappedToAllVolumes = ss.NumOfMappedToAllVolumes
+ m.ProtectionDomains = ss.NumOfProtectionDomains
+ m.RfcacheDevices = ss.NumOfRfcacheDevices
+ m.Sdc = ss.NumOfSdc
+ m.Sds = ss.NumOfSds
+ m.Snapshots = ss.NumOfSnapshots
+ m.StoragePools = ss.NumOfStoragePools
+ m.VTrees = ss.NumOfVtrees
+ m.Volumes = ss.NumOfVolumes
+ m.ThickBaseVolumes = ss.NumOfThickBaseVolumes
+ m.ThinBaseVolumes = ss.NumOfThinBaseVolumes
+ m.UnmappedVolumes = ss.NumOfUnmappedVolumes
+ m.MappedVolumes = sum(ss.NumOfVolumes, -ss.NumOfUnmappedVolumes)
+}
+
+func collectSystemWorkload(sm *systemMetrics, ss client.SystemStatistics) {
+ m := &sm.Workload
+
+ m.Total.BW.set(
+ calcBW(ss.TotalReadBwc),
+ calcBW(ss.TotalWriteBwc),
+ )
+ m.Frontend.BW.set(
+ calcBW(ss.UserDataReadBwc),
+ calcBW(ss.UserDataWriteBwc),
+ )
+ m.Backend.Primary.BW.set(
+ calcBW(ss.PrimaryReadBwc),
+ calcBW(ss.PrimaryWriteBwc),
+ )
+ m.Backend.Secondary.BW.set(
+ calcBW(ss.SecondaryReadBwc),
+ calcBW(ss.SecondaryWriteBwc),
+ )
+ m.Backend.Total.BW.set(
+ sumFloat(m.Backend.Primary.BW.Read, m.Backend.Secondary.BW.Read),
+ sumFloat(m.Backend.Primary.BW.Write, m.Backend.Secondary.BW.Write),
+ )
+
+ m.Total.IOPS.set(
+ calcIOPS(ss.TotalReadBwc),
+ calcIOPS(ss.TotalWriteBwc),
+ )
+ m.Frontend.IOPS.set(
+ calcIOPS(ss.UserDataReadBwc),
+ calcIOPS(ss.UserDataWriteBwc),
+ )
+ m.Backend.Primary.IOPS.set(
+ calcIOPS(ss.PrimaryReadBwc),
+ calcIOPS(ss.PrimaryWriteBwc),
+ )
+ m.Backend.Secondary.IOPS.set(
+ calcIOPS(ss.SecondaryReadBwc),
+ calcIOPS(ss.SecondaryWriteBwc),
+ )
+ m.Backend.Total.IOPS.set(
+ sumFloat(m.Backend.Primary.IOPS.Read, m.Backend.Secondary.IOPS.Read),
+ sumFloat(m.Backend.Primary.IOPS.Write, m.Backend.Secondary.IOPS.Write),
+ )
+
+ m.Total.IOSize.set(
+ calcIOSize(ss.TotalReadBwc),
+ calcIOSize(ss.TotalWriteBwc),
+ )
+ m.Frontend.IOSize.set(
+ calcIOSize(ss.UserDataReadBwc),
+ calcIOSize(ss.UserDataWriteBwc),
+ )
+ m.Backend.Primary.IOSize.set(
+ calcIOSize(ss.PrimaryReadBwc),
+ calcIOSize(ss.PrimaryWriteBwc),
+ )
+ m.Backend.Secondary.IOSize.set(
+ calcIOSize(ss.SecondaryReadBwc),
+ calcIOSize(ss.SecondaryWriteBwc),
+ )
+ m.Backend.Total.IOSize.set(
+ sumFloat(m.Backend.Primary.IOSize.Read, m.Backend.Secondary.IOSize.Read),
+ sumFloat(m.Backend.Primary.IOSize.Write, m.Backend.Secondary.IOSize.Write),
+ )
+}
+
+func collectSystemRebuild(sm *systemMetrics, ss client.SystemStatistics) {
+ m := &sm.Rebuild
+
+ m.Forward.BW.set(
+ calcBW(ss.FwdRebuildReadBwc),
+ calcBW(ss.FwdRebuildWriteBwc),
+ )
+ m.Backward.BW.set(
+ calcBW(ss.BckRebuildReadBwc),
+ calcBW(ss.BckRebuildWriteBwc),
+ )
+ m.Normal.BW.set(
+ calcBW(ss.NormRebuildReadBwc),
+ calcBW(ss.NormRebuildWriteBwc),
+ )
+ m.Total.BW.set(
+ sumFloat(m.Forward.BW.Read, m.Backward.BW.Read, m.Normal.BW.Read),
+ sumFloat(m.Forward.BW.Write, m.Backward.BW.Write, m.Normal.BW.Write),
+ )
+
+ m.Forward.IOPS.set(
+ calcIOPS(ss.FwdRebuildReadBwc),
+ calcIOPS(ss.FwdRebuildWriteBwc),
+ )
+ m.Backward.IOPS.set(
+ calcIOPS(ss.BckRebuildReadBwc),
+ calcIOPS(ss.BckRebuildWriteBwc),
+ )
+ m.Normal.IOPS.set(
+ calcIOPS(ss.NormRebuildReadBwc),
+ calcIOPS(ss.NormRebuildWriteBwc),
+ )
+ m.Total.IOPS.set(
+ sumFloat(m.Forward.IOPS.Read, m.Backward.IOPS.Read, m.Normal.IOPS.Read),
+ sumFloat(m.Forward.IOPS.Write, m.Backward.IOPS.Write, m.Normal.IOPS.Write),
+ )
+
+ m.Forward.IOSize.set(
+ calcIOSize(ss.FwdRebuildReadBwc),
+ calcIOSize(ss.FwdRebuildWriteBwc),
+ )
+ m.Backward.IOSize.set(
+ calcIOSize(ss.BckRebuildReadBwc),
+ calcIOSize(ss.BckRebuildWriteBwc),
+ )
+ m.Normal.IOSize.set(
+ calcIOSize(ss.NormRebuildReadBwc),
+ calcIOSize(ss.NormRebuildWriteBwc),
+ )
+ m.Total.IOSize.set(
+ sumFloat(m.Forward.IOSize.Read, m.Backward.IOSize.Read, m.Normal.IOSize.Read),
+ sumFloat(m.Forward.IOSize.Write, m.Backward.IOSize.Write, m.Normal.IOSize.Write),
+ )
+
+ m.Forward.Pending = ss.PendingFwdRebuildCapacityInKb
+ m.Backward.Pending = ss.PendingBckRebuildCapacityInKb
+ m.Normal.Pending = ss.PendingNormRebuildCapacityInKb
+ m.Total.Pending = sum(m.Forward.Pending, m.Backward.Pending, m.Normal.Pending)
+}
+
+func collectSystemRebalance(sm *systemMetrics, ss client.SystemStatistics) {
+ m := &sm.Rebalance
+
+ m.BW.set(
+ calcBW(ss.RebalanceReadBwc),
+ calcBW(ss.RebalanceWriteBwc),
+ )
+
+ m.IOPS.set(
+ calcIOPS(ss.RebalanceReadBwc),
+ calcIOPS(ss.RebalanceWriteBwc),
+ )
+
+ m.IOSize.set(
+ calcIOSize(ss.RebalanceReadBwc),
+ calcIOSize(ss.RebalanceWriteBwc),
+ )
+
+ m.Pending = ss.PendingRebalanceCapacityInKb
+ m.TimeUntilFinish = divFloat(float64(m.Pending), m.BW.ReadWrite)
+}
+
+func calcBW(bwc client.Bwc) float64 { return div(bwc.TotalWeightInKb, bwc.NumSeconds) }
+func calcIOPS(bwc client.Bwc) float64 { return div(bwc.NumOccured, bwc.NumSeconds) }
+func calcIOSize(bwc client.Bwc) float64 { return div(bwc.TotalWeightInKb, bwc.NumOccured) }
+
+func sum(a, b int64, others ...int64) (res int64) {
+ for _, v := range others {
+ res += v
+ }
+ return res + a + b
+}
+
+func sumFloat(a, b float64, others ...float64) (res float64) {
+ for _, v := range others {
+ res += v
+ }
+ return res + a + b
+}
+
+func div(a, b int64) float64 {
+ return divFloat(float64(a), float64(b))
+}
+
+func divFloat(a, b float64) float64 {
+ if b == 0 {
+ return 0
+ }
+ return a / b
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/config_schema.json b/src/go/collectors/go.d.plugin/modules/scaleio/config_schema.json
new file mode 100644
index 000000000..ba1067325
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/config_schema.json
@@ -0,0 +1,177 @@
+{
+ "jsonSchema": {
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ScaleIO collector configuration.",
+ "type": "object",
+ "properties": {
+ "update_every": {
+ "title": "Update every",
+ "description": "Data collection interval, measured in seconds.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 1
+ },
+ "url": {
+ "title": "URL",
+ "description": "The base URL of the VxFlex OS Gateway API.",
+ "type": "string",
+ "default": "http://127.0.0.1:80",
+ "format": "uri"
+ },
+ "timeout": {
+ "title": "Timeout",
+ "description": "The timeout in seconds for the HTTP request.",
+ "type": "number",
+ "minimum": 0.5,
+ "default": 1
+ },
+ "not_follow_redirects": {
+ "title": "Not follow redirects",
+ "description": "If set, the client will not follow HTTP redirects automatically.",
+ "type": "boolean"
+ },
+ "username": {
+ "title": "Username",
+ "description": "The username for basic authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "password": {
+ "title": "Password",
+ "description": "The password for basic authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "proxy_url": {
+ "title": "Proxy URL",
+ "description": "The URL of the proxy server.",
+ "type": "string"
+ },
+ "proxy_username": {
+ "title": "Proxy username",
+ "description": "The username for proxy authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "proxy_password": {
+ "title": "Proxy password",
+ "description": "The password for proxy authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "headers": {
+ "title": "Headers",
+ "description": "Additional HTTP headers to include in the request.",
+ "type": [
+ "object",
+ "null"
+ ],
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "tls_skip_verify": {
+ "title": "Skip TLS verification",
+ "description": "If set, TLS certificate verification will be skipped.",
+ "type": "boolean"
+ },
+ "tls_ca": {
+ "title": "TLS CA",
+ "description": "The path to the CA certificate file for TLS verification.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "tls_cert": {
+ "title": "TLS certificate",
+ "description": "The path to the client certificate file for TLS authentication.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "tls_key": {
+ "title": "TLS key",
+ "description": "The path to the client key file for TLS authentication.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "body": {
+ "title": "Body",
+ "type": "string"
+ },
+ "method": {
+ "title": "Method",
+ "type": "string"
+ }
+ },
+ "required": [
+ "url"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^name$": {}
+ }
+ },
+ "uiSchema": {
+ "ui:flavour": "tabs",
+ "ui:options": {
+ "tabs": [
+ {
+ "title": "Base",
+ "fields": [
+ "update_every",
+ "url",
+ "timeout",
+ "not_follow_redirects"
+ ]
+ },
+ {
+ "title": "Auth",
+ "fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "title": "TLS",
+ "fields": [
+ "tls_skip_verify",
+ "tls_ca",
+ "tls_cert",
+ "tls_key"
+ ]
+ },
+ {
+ "title": "Proxy",
+ "fields": [
+ "proxy_url",
+ "proxy_username",
+ "proxy_password"
+ ]
+ },
+ {
+ "title": "Headers",
+ "fields": [
+ "headers"
+ ]
+ }
+ ]
+ },
+ "uiOptions": {
+ "fullPage": true
+ },
+ "body": {
+ "ui:widget": "hidden"
+ },
+ "method": {
+ "ui:widget": "hidden"
+ },
+ "timeout": {
+ "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
+ },
+ "password": {
+ "ui:widget": "password"
+ },
+ "proxy_password": {
+ "ui:widget": "password"
+ }
+ }
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/integrations/dell_emc_scaleio.md b/src/go/collectors/go.d.plugin/modules/scaleio/integrations/dell_emc_scaleio.md
new file mode 100644
index 000000000..c5a977600
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/integrations/dell_emc_scaleio.md
@@ -0,0 +1,255 @@
+<!--startmeta
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/scaleio/README.md"
+meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/scaleio/metadata.yaml"
+sidebar_label: "Dell EMC ScaleIO"
+learn_status: "Published"
+learn_rel_path: "Collecting Metrics/Storage, Mount Points and Filesystems"
+most_popular: False
+message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE"
+endmeta-->
+
+# Dell EMC ScaleIO
+
+
+<img src="https://netdata.cloud/img/dell.svg" width="150"/>
+
+
+Plugin: go.d.plugin
+Module: scaleio
+
+<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
+
+## Overview
+
+This collector monitors ScaleIO (VxFlex OS) instances via VxFlex OS Gateway API.
+
+It collects metrics for the following ScaleIO components:
+
+- System
+- Storage Pool
+- Sdc
+
+
+
+
+This collector is supported on all platforms.
+
+This collector supports collecting metrics from multiple instances of this integration, including remote instances.
+
+
+### Default Behavior
+
+#### Auto-Detection
+
+This integration doesn't support auto-detection.
+
+#### Limits
+
+The default configuration for this integration does not impose any limits on data collection.
+
+#### Performance Impact
+
+The default configuration for this integration is not expected to impose a significant performance impact on the system.
+
+
+## Metrics
+
+Metrics grouped by *scope*.
+
+The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.
+
+
+
+### Per Dell EMC ScaleIO instance
+
+These metrics refer to the entire monitored application.
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| scaleio.system_capacity_total | total | KiB |
+| scaleio.system_capacity_in_use | in_use | KiB |
+| scaleio.system_capacity_usage | thick, decreased, thin, snapshot, spare, unused | KiB |
+| scaleio.system_capacity_available_volume_allocation | available | KiB |
+| scaleio.system_capacity_health_state | protected, degraded, in_maintenance, failed, unavailable | KiB |
+| scaleio.system_workload_primary_bandwidth_total | total | KiB/s |
+| scaleio.system_workload_primary_bandwidth | read, write | KiB/s |
+| scaleio.system_workload_primary_iops_total | total | iops/s |
+| scaleio.system_workload_primary_iops | read, write | iops/s |
+| scaleio.system_workload_primary_io_size_total | io_size | KiB |
+| scaleio.system_rebalance | read, write | KiB/s |
+| scaleio.system_rebalance_left | left | KiB |
+| scaleio.system_rebalance_time_until_finish | time | seconds |
+| scaleio.system_rebuild | read, write | KiB/s |
+| scaleio.system_rebuild_left | left | KiB |
+| scaleio.system_defined_components | devices, fault_sets, protection_domains, rfcache_devices, sdc, sds, snapshots, storage_pools, volumes, vtrees | components |
+| scaleio.system_components_volumes_by_type | thick, thin | volumes |
+| scaleio.system_components_volumes_by_mapping | mapped, unmapped | volumes |
+
+### Per storage pool
+
+These metrics refer to the storage pool.
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| scaleio.storage_pool_capacity_total | total | KiB |
+| scaleio.storage_pool_capacity_in_use | in_use | KiB |
+| scaleio.storage_pool_capacity_usage | thick, decreased, thin, snapshot, spare, unused | KiB |
+| scaleio.storage_pool_capacity_utilization | used | percentage |
+| scaleio.storage_pool_capacity_available_volume_allocation | available | KiB |
+| scaleio.storage_pool_capacity_health_state | protected, degraded, in_maintenance, failed, unavailable | KiB |
+| scaleio.storage_pool_components | devices, snapshots, volumes, vtrees | components |
+
+### Per sdc
+
+These metrics refer to the SDC (ScaleIO Data Client).
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| scaleio.sdc_mdm_connection_state | connected | boolean |
+| scaleio.sdc_bandwidth | read, write | KiB/s |
+| scaleio.sdc_iops | read, write | iops/s |
+| scaleio.sdc_io_size | read, write | KiB |
+| scaleio.sdc_num_of_mapped_volumed | mapped | volumes |
+
+
+
+## Alerts
+
+There are no alerts configured by default for this integration.
+
+
+## Setup
+
+### Prerequisites
+
+No action required.
+
+### Configuration
+
+#### File
+
+The configuration file name for this integration is `go.d/scaleio.conf`.
+
+
+You can edit the configuration file using the `edit-config` script from the
+Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory).
+
+```bash
+cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
+sudo ./edit-config go.d/scaleio.conf
+```
+#### Options
+
+The following options can be defined globally: update_every, autodetection_retry.
+
+
+<details open><summary>Config options</summary>
+
+| Name | Description | Default | Required |
+|:----|:-----------|:-------|:--------:|
+| update_every | Data collection frequency. | 5 | no |
+| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no |
+| url | Server URL. | https://127.0.0.1:80 | yes |
+| timeout | HTTP request timeout. | 1 | no |
+| username | Username for basic HTTP authentication. | | yes |
+| password | Password for basic HTTP authentication. | | yes |
+| proxy_url | Proxy URL. | | no |
+| proxy_username | Username for proxy basic HTTP authentication. | | no |
+| proxy_password | Password for proxy basic HTTP authentication. | | no |
+| method | HTTP request method. | GET | no |
+| body | HTTP request body. | | no |
+| headers | HTTP request headers. | | no |
+| not_follow_redirects | Redirect handling policy. Controls whether the client follows redirects. | no | no |
+| tls_skip_verify | Server certificate chain and hostname validation policy. Controls whether the client performs this check. | no | no |
+| tls_ca | Certification authority that the client uses when verifying the server's certificates. | | no |
+| tls_cert | Client TLS certificate. | | no |
+| tls_key | Client TLS key. | | no |
+
+</details>
+
+#### Examples
+
+##### Basic
+
+An example configuration.
+
+<details open><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: https://127.0.0.1
+ username: admin
+ password: password
+ tls_skip_verify: yes # self-signed certificate
+
+```
+</details>
+
+##### Multi-instance
+
+> **Note**: When you define multiple jobs, their names must be unique.
+
+Local and remote instance.
+
+
+<details open><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: https://127.0.0.1
+ username: admin
+ password: password
+ tls_skip_verify: yes # self-signed certificate
+
+ - name: remote
+ url: https://203.0.113.10
+ username: admin
+ password: password
+ tls_skip_verify: yes
+
+```
+</details>
+
+
+
+## Troubleshooting
+
+### Debug Mode
+
+To troubleshoot issues with the `scaleio` collector, run the `go.d.plugin` with the debug option enabled. The output
+should give you clues as to why the collector isn't working.
+
+- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on
+ your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`.
+
+ ```bash
+ cd /usr/libexec/netdata/plugins.d/
+ ```
+
+- Switch to the `netdata` user.
+
+ ```bash
+ sudo -u netdata -s
+ ```
+
+- Run the `go.d.plugin` to debug the collector:
+
+ ```bash
+ ./go.d.plugin -d -m scaleio
+ ```
+
+
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/metadata.yaml b/src/go/collectors/go.d.plugin/modules/scaleio/metadata.yaml
new file mode 100644
index 000000000..edee6fc8b
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/metadata.yaml
@@ -0,0 +1,399 @@
+plugin_name: go.d.plugin
+modules:
+ - meta:
+ id: collector-go.d.plugin-scaleio
+ plugin_name: go.d.plugin
+ module_name: scaleio
+ monitored_instance:
+ name: Dell EMC ScaleIO
+ link: https://www.dell.com/en-ca/dt/storage/scaleio/scaleioreadynode.htm
+ icon_filename: dell.svg
+ categories:
+ - data-collection.storage-mount-points-and-filesystems
+ keywords:
+ - scaleio
+ related_resources:
+ integrations:
+ list: []
+ info_provided_to_referring_integrations:
+ description: ""
+ most_popular: false
+ overview:
+ data_collection:
+ metrics_description: |
+ This collector monitors ScaleIO (VxFlex OS) instances via VxFlex OS Gateway API.
+
+ It collects metrics for the following ScaleIO components:
+
+ - System
+ - Storage Pool
+ - Sdc
+ method_description: ""
+ supported_platforms:
+ include: []
+ exclude: []
+ multi_instance: true
+ additional_permissions:
+ description: ""
+ default_behavior:
+ auto_detection:
+ description: ""
+ limits:
+ description: ""
+ performance_impact:
+ description: ""
+ setup:
+ prerequisites:
+ list: []
+ configuration:
+ file:
+ name: go.d/scaleio.conf
+ options:
+ description: |
+ The following options can be defined globally: update_every, autodetection_retry.
+ folding:
+ title: Config options
+ enabled: true
+ list:
+ - name: update_every
+ description: Data collection frequency.
+ default_value: 5
+ required: false
+ - name: autodetection_retry
+ description: Recheck interval in seconds. Zero means no recheck will be scheduled.
+ default_value: 0
+ required: false
+ - name: url
+ description: Server URL.
+ default_value: https://127.0.0.1:80
+ required: true
+ - name: timeout
+ description: HTTP request timeout.
+ default_value: 1
+ required: false
+ - name: username
+ description: Username for basic HTTP authentication.
+ default_value: ""
+ required: true
+ - name: password
+ description: Password for basic HTTP authentication.
+ default_value: ""
+ required: true
+ - name: proxy_url
+ description: Proxy URL.
+ default_value: ""
+ required: false
+ - name: proxy_username
+ description: Username for proxy basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: proxy_password
+ description: Password for proxy basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: method
+ description: HTTP request method.
+ default_value: GET
+ required: false
+ - name: body
+ description: HTTP request body.
+ default_value: ""
+ required: false
+ - name: headers
+ description: HTTP request headers.
+ default_value: ""
+ required: false
+ - name: not_follow_redirects
+ description: Redirect handling policy. Controls whether the client follows redirects.
+ default_value: false
+ required: false
+ - name: tls_skip_verify
+ description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
+ default_value: false
+ required: false
+ - name: tls_ca
+ description: Certification authority that the client uses when verifying the server's certificates.
+ default_value: ""
+ required: false
+ - name: tls_cert
+ description: Client TLS certificate.
+ default_value: ""
+ required: false
+ - name: tls_key
+ description: Client TLS key.
+ default_value: ""
+ required: false
+ examples:
+ folding:
+ title: Config
+ enabled: true
+ list:
+ - name: Basic
+ description: An example configuration.
+ config: |
+ jobs:
+ - name: local
+ url: https://127.0.0.1
+ username: admin
+ password: password
+ tls_skip_verify: yes # self-signed certificate
+ - name: Multi-instance
+ description: |
+ > **Note**: When you define multiple jobs, their names must be unique.
+
+ Local and remote instance.
+ config: |
+ jobs:
+ - name: local
+ url: https://127.0.0.1
+ username: admin
+ password: password
+ tls_skip_verify: yes # self-signed certificate
+
+ - name: remote
+ url: https://203.0.113.10
+ username: admin
+ password: password
+ tls_skip_verify: yes
+ troubleshooting:
+ problems:
+ list: []
+ alerts: []
+ metrics:
+ folding:
+ title: Metrics
+ enabled: false
+ description: ""
+ availability: []
+ scopes:
+ - name: global
+ description: These metrics refer to the entire monitored application.
+ labels: []
+ metrics:
+ - name: scaleio.system_capacity_total
+ description: Total Capacity
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: total
+ - name: scaleio.system_capacity_in_use
+ description: Capacity In Use
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: in_use
+ - name: scaleio.system_capacity_usage
+ description: Capacity Usage
+ unit: KiB
+ chart_type: stacked
+ dimensions:
+ - name: thick
+ - name: decreased
+ - name: thin
+ - name: snapshot
+ - name: spare
+ - name: unused
+ - name: scaleio.system_capacity_available_volume_allocation
+ description: Available For Volume Allocation
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: available
+ - name: scaleio.system_capacity_health_state
+ description: Capacity Health State
+ unit: KiB
+ chart_type: stacked
+ dimensions:
+ - name: protected
+ - name: degraded
+ - name: in_maintenance
+ - name: failed
+ - name: unavailable
+ - name: scaleio.system_workload_primary_bandwidth_total
+ description: Primary Backend Bandwidth Total (Read and Write)
+ unit: KiB/s
+ chart_type: line
+ dimensions:
+ - name: total
+ - name: scaleio.system_workload_primary_bandwidth
+ description: Primary Backend Bandwidth
+ unit: KiB/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.system_workload_primary_iops_total
+ description: Primary Backend IOPS Total (Read and Write)
+ unit: iops/s
+ chart_type: line
+ dimensions:
+ - name: total
+ - name: scaleio.system_workload_primary_iops
+ description: Primary Backend IOPS
+ unit: iops/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.system_workload_primary_io_size_total
+ description: Primary Backend I/O Size Total (Read and Write)
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: io_size
+ - name: scaleio.system_rebalance
+ description: Rebalance
+ unit: KiB/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.system_rebalance_left
+ description: Rebalance Pending Capacity
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: left
+ - name: scaleio.system_rebalance_time_until_finish
+ description: Rebalance Approximate Time Until Finish
+ unit: seconds
+ chart_type: line
+ dimensions:
+ - name: time
+ - name: scaleio.system_rebuild
+ description: Rebuild Bandwidth Total (Forward, Backward and Normal)
+ unit: KiB/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.system_rebuild_left
+ description: Rebuild Pending Capacity Total (Forward, Backward and Normal)
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: left
+ - name: scaleio.system_defined_components
+ description: Components
+ unit: components
+ chart_type: line
+ dimensions:
+ - name: devices
+ - name: fault_sets
+ - name: protection_domains
+ - name: rfcache_devices
+ - name: sdc
+ - name: sds
+ - name: snapshots
+ - name: storage_pools
+ - name: volumes
+ - name: vtrees
+ - name: scaleio.system_components_volumes_by_type
+ description: Volumes By Type
+ unit: volumes
+ chart_type: stacked
+ dimensions:
+ - name: thick
+ - name: thin
+ - name: scaleio.system_components_volumes_by_mapping
+ description: Volumes By Mapping
+ unit: volumes
+ chart_type: stacked
+ dimensions:
+ - name: mapped
+ - name: unmapped
+ - name: storage pool
+ description: These metrics refer to the storage pool.
+ labels: []
+ metrics:
+ - name: scaleio.storage_pool_capacity_total
+ description: Total Capacity
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: total
+ - name: scaleio.storage_pool_capacity_in_use
+ description: Capacity In Use
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: in_use
+ - name: scaleio.storage_pool_capacity_usage
+ description: Capacity Usage
+ unit: KiB
+ chart_type: stacked
+ dimensions:
+ - name: thick
+ - name: decreased
+ - name: thin
+ - name: snapshot
+ - name: spare
+ - name: unused
+ - name: scaleio.storage_pool_capacity_utilization
+ description: Capacity Utilization
+ unit: percentage
+ chart_type: line
+ dimensions:
+ - name: used
+ - name: scaleio.storage_pool_capacity_available_volume_allocation
+ description: Available For Volume Allocation
+ unit: KiB
+ chart_type: line
+ dimensions:
+ - name: available
+ - name: scaleio.storage_pool_capacity_health_state
+ description: Capacity Health State
+ unit: KiB
+ chart_type: stacked
+ dimensions:
+ - name: protected
+ - name: degraded
+ - name: in_maintenance
+ - name: failed
+ - name: unavailable
+ - name: scaleio.storage_pool_components
+ description: Components
+ unit: components
+ chart_type: line
+ dimensions:
+ - name: devices
+ - name: snapshots
+ - name: volumes
+ - name: vtrees
+ - name: sdc
+ description: These metrics refer to the SDC (ScaleIO Data Client).
+ labels: []
+ metrics:
+ - name: scaleio.sdc_mdm_connection_state
+ description: MDM Connection State
+ unit: boolean
+ chart_type: line
+ dimensions:
+ - name: connected
+ - name: scaleio.sdc_bandwidth
+ description: Bandwidth
+ unit: KiB/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.sdc_iops
+ description: IOPS
+ unit: iops/s
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.sdc_io_size
+ description: IOPS Size
+ unit: KiB
+ chart_type: area
+ dimensions:
+ - name: read
+ - name: write
+ - name: scaleio.sdc_num_of_mapped_volumed
+ description: Mapped Volumes
+ unit: volumes
+ chart_type: line
+ dimensions:
+ - name: mapped
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/metrics.go b/src/go/collectors/go.d.plugin/modules/scaleio/metrics.go
new file mode 100644
index 000000000..a5a9b9810
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/metrics.go
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+type metrics struct {
+ System systemMetrics `stm:"system"`
+ Sdc map[string]sdcMetrics `stm:"sdc"`
+ StoragePool map[string]storagePoolMetrics `stm:"storage_pool"`
+}
+
+type capacity struct {
+ MaxCapacity int64 `stm:"max_capacity"`
+ ThickInUse int64 `stm:"thick_in_use"`
+ ThinInUse int64 `stm:"thin_in_use"`
+ Snapshot int64 `stm:"snapshot"`
+ Spare int64 `stm:"spare"`
+ Decreased int64 `stm:"decreased"` // not in statistics, should be calculated
+ Unused int64 `stm:"unused"`
+
+ InUse int64 `stm:"in_use"`
+ AvailableForVolumeAllocation int64 `stm:"available_for_volume_allocation"`
+
+ Protected int64 `stm:"protected"`
+ InMaintenance int64 `stm:"in_maintenance"`
+ Degraded int64 `stm:"degraded"`
+ Failed int64 `stm:"failed"`
+ UnreachableUnused int64 `stm:"unreachable_unused"`
+}
+
+type (
+ systemMetrics struct {
+ Capacity systemCapacity `stm:"capacity"`
+ Workload systemWorkload `stm:""`
+ Rebalance systemRebalance `stm:"rebalance"`
+ Rebuild systemRebuild `stm:"rebuild"`
+ Components systemComponents `stm:"num_of"`
+ }
+ systemCapacity = capacity
+ systemComponents struct {
+ Devices int64 `stm:"devices"`
+ FaultSets int64 `stm:"fault_sets"`
+ ProtectionDomains int64 `stm:"protection_domains"`
+ RfcacheDevices int64 `stm:"rfcache_devices"`
+ Sdc int64 `stm:"sdc"`
+ Sds int64 `stm:"sds"`
+ Snapshots int64 `stm:"snapshots"`
+ StoragePools int64 `stm:"storage_pools"`
+ MappedToAllVolumes int64 `stm:"mapped_to_all_volumes"`
+ ThickBaseVolumes int64 `stm:"thick_base_volumes"`
+ ThinBaseVolumes int64 `stm:"thin_base_volumes"`
+ UnmappedVolumes int64 `stm:"unmapped_volumes"`
+ MappedVolumes int64 `stm:"mapped_volumes"`
+ Volumes int64 `stm:"volumes"`
+ VTrees int64 `stm:"vtrees"`
+ }
+ systemWorkload struct {
+ Total bwIOPS `stm:"total"`
+ Backend struct {
+ Total bwIOPS `stm:"total"`
+ Primary bwIOPS `stm:"primary"`
+ Secondary bwIOPS `stm:"secondary"`
+ } `stm:"backend"`
+ Frontend bwIOPS `stm:"frontend_user_data"`
+ }
+ systemRebalance struct {
+ TimeUntilFinish float64 `stm:"time_until_finish"`
+ bwIOPSPending `stm:""`
+ }
+ systemRebuild struct {
+ Total bwIOPSPending `stm:"total"`
+ Forward bwIOPSPending `stm:"forward"`
+ Backward bwIOPSPending `stm:"backward"`
+ Normal bwIOPSPending `stm:"normal"`
+ }
+)
+
+type (
+ sdcMetrics struct {
+ bwIOPS `stm:""`
+ MappedVolumes int64 `stm:"num_of_mapped_volumes"`
+ MDMConnectionState bool `stm:"mdm_connection_state"`
+ }
+)
+
+type (
+ storagePoolMetrics struct {
+ Capacity storagePoolCapacity `stm:"capacity"`
+ Components struct {
+ Devices int64 `stm:"devices"`
+ Volumes int64 `stm:"volumes"`
+ Vtrees int64 `stm:"vtrees"`
+ Snapshots int64 `stm:"snapshots"`
+ } `stm:"num_of"`
+ }
+ storagePoolCapacity struct {
+ capacity `stm:""`
+ Utilization float64 `stm:"utilization,100,1"` // TODO: only StoragePool (sparePercentage)
+ AlertThreshold struct {
+ Critical int64 `stm:"critical_threshold"`
+ High int64 `stm:"high_threshold"`
+ } `stm:"alert"`
+ }
+)
+
+type (
+ readWrite struct {
+ Read float64 `stm:"read,1000,1"`
+ Write float64 `stm:"write,1000,1"`
+ ReadWrite float64 `stm:"read_write,1000,1"`
+ }
+ bwIOPS struct {
+ BW readWrite `stm:"bandwidth"`
+ IOPS readWrite `stm:"iops"`
+ IOSize readWrite `stm:"io_size"`
+ }
+ bwIOPSPending struct {
+ bwIOPS `stm:""`
+ Pending int64 `stm:"pending_capacity_in_Kb"`
+ }
+)
+
+func (rw *readWrite) set(r, w float64) {
+ rw.Read = r
+ rw.Write = w
+ rw.ReadWrite = r + w
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/queries.go b/src/go/collectors/go.d.plugin/modules/scaleio/queries.go
new file mode 100644
index 000000000..265c3b874
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/queries.go
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+/*
+Starting from version 3 of ScaleIO/VxFlex API numOfScsiInitiators property is removed from the system selectedStatisticsQuery.
+Reference: VxFlex OS v3.x REST API Reference Guide.pdf
+*/
+
+var query = client.SelectedStatisticsQuery{
+ List: []client.SelectedObject{
+ {
+ Type: "System",
+ Properties: []string{
+ "maxCapacityInKb",
+ "thickCapacityInUseInKb",
+ "thinCapacityInUseInKb",
+ "snapCapacityInUseOccupiedInKb",
+ "spareCapacityInKb",
+ "capacityLimitInKb",
+
+ "protectedCapacityInKb",
+ "degradedHealthyCapacityInKb",
+ "degradedFailedCapacityInKb",
+ "failedCapacityInKb",
+ "unreachableUnusedCapacityInKb",
+ "inMaintenanceCapacityInKb",
+
+ "capacityInUseInKb",
+ "capacityAvailableForVolumeAllocationInKb",
+
+ "numOfDevices",
+ "numOfFaultSets",
+ "numOfProtectionDomains",
+ "numOfRfcacheDevices",
+ "numOfSdc",
+ "numOfSds",
+ "numOfSnapshots",
+ "numOfStoragePools",
+ "numOfVolumes",
+ "numOfVtrees",
+ "numOfThickBaseVolumes",
+ "numOfThinBaseVolumes",
+ "numOfMappedToAllVolumes",
+ "numOfUnmappedVolumes",
+
+ "rebalanceReadBwc",
+ "rebalanceWriteBwc",
+ "pendingRebalanceCapacityInKb",
+
+ "pendingNormRebuildCapacityInKb",
+ "pendingBckRebuildCapacityInKb",
+ "pendingFwdRebuildCapacityInKb",
+ "normRebuildReadBwc",
+ "normRebuildWriteBwc",
+ "bckRebuildReadBwc",
+ "bckRebuildWriteBwc",
+ "fwdRebuildReadBwc",
+ "fwdRebuildWriteBwc",
+
+ "primaryReadBwc",
+ "primaryWriteBwc",
+ "secondaryReadBwc",
+ "secondaryWriteBwc",
+ "userDataReadBwc",
+ "userDataWriteBwc",
+ "totalReadBwc",
+ "totalWriteBwc",
+ },
+ },
+ {
+ Type: "StoragePool",
+ AllIDs: true,
+ Properties: []string{
+ "maxCapacityInKb",
+ "thickCapacityInUseInKb",
+ "thinCapacityInUseInKb",
+ "snapCapacityInUseOccupiedInKb",
+ "spareCapacityInKb",
+ "capacityLimitInKb",
+
+ "protectedCapacityInKb",
+ "degradedHealthyCapacityInKb",
+ "degradedFailedCapacityInKb",
+ "failedCapacityInKb",
+ "unreachableUnusedCapacityInKb",
+ "inMaintenanceCapacityInKb",
+
+ "capacityInUseInKb",
+ "capacityAvailableForVolumeAllocationInKb",
+
+ "numOfDevices",
+ "numOfVolumes",
+ "numOfVtrees",
+ "numOfSnapshots",
+ },
+ },
+ {
+ Type: "Sdc",
+ AllIDs: true,
+ Properties: []string{
+ "userDataReadBwc",
+ "userDataWriteBwc",
+
+ "numOfMappedVolumes",
+ },
+ },
+ },
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/scaleio.go b/src/go/collectors/go.d.plugin/modules/scaleio/scaleio.go
new file mode 100644
index 000000000..4cc8e69a9
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/scaleio.go
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import (
+ _ "embed"
+ "errors"
+ "time"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+ "github.com/netdata/netdata/go/go.d.plugin/pkg/web"
+)
+
+//go:embed "config_schema.json"
+var configSchema string
+
+func init() {
+ module.Register("scaleio", module.Creator{
+ JobConfigSchema: configSchema,
+ Create: func() module.Module { return New() },
+ Config: func() any { return &Config{} },
+ })
+}
+
+func New() *ScaleIO {
+ return &ScaleIO{
+ Config: Config{
+ HTTP: web.HTTP{
+ Request: web.Request{
+ URL: "https://127.0.0.1",
+ },
+ Client: web.Client{
+ Timeout: web.Duration(time.Second),
+ },
+ },
+ },
+ charts: systemCharts.Copy(),
+ charted: make(map[string]bool),
+ }
+}
+
+type Config struct {
+ UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
+ web.HTTP `yaml:",inline" json:""`
+}
+
+type (
+ ScaleIO struct {
+ module.Base
+ Config `yaml:",inline" json:""`
+
+ charts *module.Charts
+
+ client *client.Client
+
+ discovered instances
+ charted map[string]bool
+ lastDiscoveryOK bool
+ runs int
+ }
+ instances struct {
+ sdc map[string]client.Sdc
+ pool map[string]client.StoragePool
+ }
+)
+
+func (s *ScaleIO) Configuration() any {
+ return s.Config
+}
+
+func (s *ScaleIO) Init() error {
+ if s.Username == "" || s.Password == "" {
+ s.Error("username and password aren't set")
+ return errors.New("username and password aren't set")
+ }
+
+ c, err := client.New(s.Client, s.Request)
+ if err != nil {
+ s.Errorf("error on creating ScaleIO client: %v", err)
+ return err
+ }
+ s.client = c
+
+ s.Debugf("using URL %s", s.URL)
+ s.Debugf("using timeout: %s", s.Timeout)
+
+ return nil
+}
+
+func (s *ScaleIO) Check() error {
+ if err := s.client.Login(); err != nil {
+ s.Error(err)
+ return err
+ }
+ mx, err := s.collect()
+ if err != nil {
+ s.Error(err)
+ return err
+ }
+ if len(mx) == 0 {
+ return errors.New("no metrics collected")
+ }
+ return nil
+}
+
+func (s *ScaleIO) Charts() *module.Charts {
+ return s.charts
+}
+
+func (s *ScaleIO) Collect() map[string]int64 {
+ mx, err := s.collect()
+ if err != nil {
+ s.Error(err)
+ return nil
+ }
+
+ if len(mx) == 0 {
+ return nil
+ }
+ return mx
+}
+
+func (s *ScaleIO) Cleanup() {
+ if s.client == nil {
+ return
+ }
+ _ = s.client.Logout()
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/scaleio_test.go b/src/go/collectors/go.d.plugin/modules/scaleio/scaleio_test.go
new file mode 100644
index 000000000..970ee263d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/scaleio_test.go
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package scaleio
+
+import (
+ "encoding/json"
+ "net/http/httptest"
+ "os"
+ "testing"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/go.d.plugin/modules/scaleio/client"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ dataConfigJSON, _ = os.ReadFile("testdata/config.json")
+ dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
+
+ dataSelectedStatistics, _ = os.ReadFile("testdata/selected_statistics.json")
+ dataInstances, _ = os.ReadFile("testdata/instances.json")
+)
+
+func Test_testDataIsValid(t *testing.T) {
+ for name, data := range map[string][]byte{
+ "dataConfigJSON": dataConfigJSON,
+ "dataConfigYAML": dataConfigYAML,
+ "dataSelectedStatistics": dataSelectedStatistics,
+ "dataInstances": dataInstances,
+ } {
+ require.NotNil(t, data, name)
+ }
+}
+
+func TestScaleIO_ConfigurationSerialize(t *testing.T) {
+ module.TestConfigurationSerialize(t, &ScaleIO{}, dataConfigJSON, dataConfigYAML)
+}
+
+func TestScaleIO_Init(t *testing.T) {
+ scaleIO := New()
+ scaleIO.Username = "username"
+ scaleIO.Password = "password"
+
+ assert.NoError(t, scaleIO.Init())
+}
+func TestScaleIO_Init_UsernameAndPasswordNotSet(t *testing.T) {
+ assert.Error(t, New().Init())
+}
+
+func TestScaleIO_Init_ErrorOnCreatingClientWrongTLSCA(t *testing.T) {
+ job := New()
+ job.Username = "username"
+ job.Password = "password"
+ job.Client.TLSConfig.TLSCA = "testdata/tls"
+
+ assert.Error(t, job.Init())
+}
+
+func TestScaleIO_Check(t *testing.T) {
+ srv, _, scaleIO := prepareSrvMockScaleIO(t)
+ defer srv.Close()
+ require.NoError(t, scaleIO.Init())
+
+ assert.NoError(t, scaleIO.Check())
+}
+
+func TestScaleIO_Check_ErrorOnLogin(t *testing.T) {
+ srv, mock, scaleIO := prepareSrvMockScaleIO(t)
+ defer srv.Close()
+ require.NoError(t, scaleIO.Init())
+ mock.Password = "new password"
+
+ assert.Error(t, scaleIO.Check())
+}
+
+func TestScaleIO_Charts(t *testing.T) {
+ assert.NotNil(t, New().Charts())
+}
+
+func TestScaleIO_Cleanup(t *testing.T) {
+ srv, _, scaleIO := prepareSrvMockScaleIO(t)
+ defer srv.Close()
+ require.NoError(t, scaleIO.Init())
+ require.NoError(t, scaleIO.Check())
+
+ scaleIO.Cleanup()
+ assert.False(t, scaleIO.client.LoggedIn())
+}
+
+func TestScaleIO_Collect(t *testing.T) {
+ srv, _, scaleIO := prepareSrvMockScaleIO(t)
+ defer srv.Close()
+ require.NoError(t, scaleIO.Init())
+ require.NoError(t, scaleIO.Check())
+
+ expected := map[string]int64{
+ "sdc_6076fd0f00000000_bandwidth_read": 0,
+ "sdc_6076fd0f00000000_bandwidth_read_write": 0,
+ "sdc_6076fd0f00000000_bandwidth_write": 0,
+ "sdc_6076fd0f00000000_io_size_read": 0,
+ "sdc_6076fd0f00000000_io_size_read_write": 0,
+ "sdc_6076fd0f00000000_io_size_write": 0,
+ "sdc_6076fd0f00000000_iops_read": 0,
+ "sdc_6076fd0f00000000_iops_read_write": 0,
+ "sdc_6076fd0f00000000_iops_write": 0,
+ "sdc_6076fd0f00000000_mdm_connection_state": 1,
+ "sdc_6076fd0f00000000_num_of_mapped_volumes": 1,
+ "sdc_6076fd1000000001_bandwidth_read": 1000,
+ "sdc_6076fd1000000001_bandwidth_read_write": 117400000,
+ "sdc_6076fd1000000001_bandwidth_write": 117399000,
+ "sdc_6076fd1000000001_io_size_read": 1000,
+ "sdc_6076fd1000000001_io_size_read_write": 695668,
+ "sdc_6076fd1000000001_io_size_write": 694668,
+ "sdc_6076fd1000000001_iops_read": 1000,
+ "sdc_6076fd1000000001_iops_read_write": 170000,
+ "sdc_6076fd1000000001_iops_write": 169000,
+ "sdc_6076fd1000000001_mdm_connection_state": 0,
+ "sdc_6076fd1000000001_num_of_mapped_volumes": 1,
+ "sdc_6076fd1100000002_bandwidth_read": 0,
+ "sdc_6076fd1100000002_bandwidth_read_write": 118972000,
+ "sdc_6076fd1100000002_bandwidth_write": 118972000,
+ "sdc_6076fd1100000002_io_size_read": 0,
+ "sdc_6076fd1100000002_io_size_read_write": 820496,
+ "sdc_6076fd1100000002_io_size_write": 820496,
+ "sdc_6076fd1100000002_iops_read": 0,
+ "sdc_6076fd1100000002_iops_read_write": 145000,
+ "sdc_6076fd1100000002_iops_write": 145000,
+ "sdc_6076fd1100000002_mdm_connection_state": 0,
+ "sdc_6076fd1100000002_num_of_mapped_volumes": 1,
+ "storage_pool_40395b7b00000000_capacity_alert_critical_threshold": 90,
+ "storage_pool_40395b7b00000000_capacity_alert_high_threshold": 80,
+ "storage_pool_40395b7b00000000_capacity_available_for_volume_allocation": 100663296,
+ "storage_pool_40395b7b00000000_capacity_decreased": 0,
+ "storage_pool_40395b7b00000000_capacity_degraded": 0,
+ "storage_pool_40395b7b00000000_capacity_failed": 0,
+ "storage_pool_40395b7b00000000_capacity_in_maintenance": 0,
+ "storage_pool_40395b7b00000000_capacity_in_use": 50110464,
+ "storage_pool_40395b7b00000000_capacity_max_capacity": 311424000,
+ "storage_pool_40395b7b00000000_capacity_protected": 50110464,
+ "storage_pool_40395b7b00000000_capacity_snapshot": 749568,
+ "storage_pool_40395b7b00000000_capacity_spare": 31141888,
+ "storage_pool_40395b7b00000000_capacity_thick_in_use": 0,
+ "storage_pool_40395b7b00000000_capacity_thin_in_use": 49360896,
+ "storage_pool_40395b7b00000000_capacity_unreachable_unused": 0,
+ "storage_pool_40395b7b00000000_capacity_unused": 229422080,
+ "storage_pool_40395b7b00000000_capacity_utilization": 1787,
+ "storage_pool_40395b7b00000000_num_of_devices": 3,
+ "storage_pool_40395b7b00000000_num_of_snapshots": 1,
+ "storage_pool_40395b7b00000000_num_of_volumes": 3,
+ "storage_pool_40395b7b00000000_num_of_vtrees": 2,
+ "storage_pool_4039828b00000001_capacity_alert_critical_threshold": 90,
+ "storage_pool_4039828b00000001_capacity_alert_high_threshold": 80,
+ "storage_pool_4039828b00000001_capacity_available_for_volume_allocation": 142606336,
+ "storage_pool_4039828b00000001_capacity_decreased": 0,
+ "storage_pool_4039828b00000001_capacity_degraded": 0,
+ "storage_pool_4039828b00000001_capacity_failed": 0,
+ "storage_pool_4039828b00000001_capacity_in_maintenance": 0,
+ "storage_pool_4039828b00000001_capacity_in_use": 0,
+ "storage_pool_4039828b00000001_capacity_max_capacity": 332395520,
+ "storage_pool_4039828b00000001_capacity_protected": 0,
+ "storage_pool_4039828b00000001_capacity_snapshot": 0,
+ "storage_pool_4039828b00000001_capacity_spare": 33239040,
+ "storage_pool_4039828b00000001_capacity_thick_in_use": 0,
+ "storage_pool_4039828b00000001_capacity_thin_in_use": 0,
+ "storage_pool_4039828b00000001_capacity_unreachable_unused": 0,
+ "storage_pool_4039828b00000001_capacity_unused": 299156480,
+ "storage_pool_4039828b00000001_capacity_utilization": 0,
+ "storage_pool_4039828b00000001_num_of_devices": 3,
+ "storage_pool_4039828b00000001_num_of_snapshots": 0,
+ "storage_pool_4039828b00000001_num_of_volumes": 0,
+ "storage_pool_4039828b00000001_num_of_vtrees": 0,
+ "system_backend_primary_bandwidth_read": 800,
+ "system_backend_primary_bandwidth_read_write": 238682400,
+ "system_backend_primary_bandwidth_write": 238681600,
+ "system_backend_primary_io_size_read": 4000,
+ "system_backend_primary_io_size_read_write": 770971,
+ "system_backend_primary_io_size_write": 766971,
+ "system_backend_primary_iops_read": 200,
+ "system_backend_primary_iops_read_write": 311400,
+ "system_backend_primary_iops_write": 311200,
+ "system_backend_secondary_bandwidth_read": 0,
+ "system_backend_secondary_bandwidth_read_write": 233926400,
+ "system_backend_secondary_bandwidth_write": 233926400,
+ "system_backend_secondary_io_size_read": 0,
+ "system_backend_secondary_io_size_read_write": 764465,
+ "system_backend_secondary_io_size_write": 764465,
+ "system_backend_secondary_iops_read": 0,
+ "system_backend_secondary_iops_read_write": 306000,
+ "system_backend_secondary_iops_write": 306000,
+ "system_backend_total_bandwidth_read": 800,
+ "system_backend_total_bandwidth_read_write": 472608800,
+ "system_backend_total_bandwidth_write": 472608000,
+ "system_backend_total_io_size_read": 4000,
+ "system_backend_total_io_size_read_write": 1535437,
+ "system_backend_total_io_size_write": 1531437,
+ "system_backend_total_iops_read": 200,
+ "system_backend_total_iops_read_write": 617400,
+ "system_backend_total_iops_write": 617200,
+ "system_capacity_available_for_volume_allocation": 243269632,
+ "system_capacity_decreased": 0,
+ "system_capacity_degraded": 0,
+ "system_capacity_failed": 0,
+ "system_capacity_in_maintenance": 0,
+ "system_capacity_in_use": 50110464,
+ "system_capacity_max_capacity": 643819520,
+ "system_capacity_protected": 50110464,
+ "system_capacity_snapshot": 749568,
+ "system_capacity_spare": 64380928,
+ "system_capacity_thick_in_use": 0,
+ "system_capacity_thin_in_use": 49360896,
+ "system_capacity_unreachable_unused": 0,
+ "system_capacity_unused": 528578560,
+ "system_frontend_user_data_bandwidth_read": 0,
+ "system_frontend_user_data_bandwidth_read_write": 227170000,
+ "system_frontend_user_data_bandwidth_write": 227170000,
+ "system_frontend_user_data_io_size_read": 0,
+ "system_frontend_user_data_io_size_read_write": 797087,
+ "system_frontend_user_data_io_size_write": 797087,
+ "system_frontend_user_data_iops_read": 0,
+ "system_frontend_user_data_iops_read_write": 285000,
+ "system_frontend_user_data_iops_write": 285000,
+ "system_num_of_devices": 6,
+ "system_num_of_fault_sets": 0,
+ "system_num_of_mapped_to_all_volumes": 0,
+ "system_num_of_mapped_volumes": 3,
+ "system_num_of_protection_domains": 1,
+ "system_num_of_rfcache_devices": 0,
+ "system_num_of_sdc": 3,
+ "system_num_of_sds": 3,
+ "system_num_of_snapshots": 1,
+ "system_num_of_storage_pools": 2,
+ "system_num_of_thick_base_volumes": 0,
+ "system_num_of_thin_base_volumes": 2,
+ "system_num_of_unmapped_volumes": 0,
+ "system_num_of_volumes": 3,
+ "system_num_of_vtrees": 2,
+ "system_rebalance_bandwidth_read": 0,
+ "system_rebalance_bandwidth_read_write": 0,
+ "system_rebalance_bandwidth_write": 0,
+ "system_rebalance_io_size_read": 0,
+ "system_rebalance_io_size_read_write": 0,
+ "system_rebalance_io_size_write": 0,
+ "system_rebalance_iops_read": 0,
+ "system_rebalance_iops_read_write": 0,
+ "system_rebalance_iops_write": 0,
+ "system_rebalance_pending_capacity_in_Kb": 0,
+ "system_rebalance_time_until_finish": 0,
+ "system_rebuild_backward_bandwidth_read": 0,
+ "system_rebuild_backward_bandwidth_read_write": 0,
+ "system_rebuild_backward_bandwidth_write": 0,
+ "system_rebuild_backward_io_size_read": 0,
+ "system_rebuild_backward_io_size_read_write": 0,
+ "system_rebuild_backward_io_size_write": 0,
+ "system_rebuild_backward_iops_read": 0,
+ "system_rebuild_backward_iops_read_write": 0,
+ "system_rebuild_backward_iops_write": 0,
+ "system_rebuild_backward_pending_capacity_in_Kb": 0,
+ "system_rebuild_forward_bandwidth_read": 0,
+ "system_rebuild_forward_bandwidth_read_write": 0,
+ "system_rebuild_forward_bandwidth_write": 0,
+ "system_rebuild_forward_io_size_read": 0,
+ "system_rebuild_forward_io_size_read_write": 0,
+ "system_rebuild_forward_io_size_write": 0,
+ "system_rebuild_forward_iops_read": 0,
+ "system_rebuild_forward_iops_read_write": 0,
+ "system_rebuild_forward_iops_write": 0,
+ "system_rebuild_forward_pending_capacity_in_Kb": 0,
+ "system_rebuild_normal_bandwidth_read": 0,
+ "system_rebuild_normal_bandwidth_read_write": 0,
+ "system_rebuild_normal_bandwidth_write": 0,
+ "system_rebuild_normal_io_size_read": 0,
+ "system_rebuild_normal_io_size_read_write": 0,
+ "system_rebuild_normal_io_size_write": 0,
+ "system_rebuild_normal_iops_read": 0,
+ "system_rebuild_normal_iops_read_write": 0,
+ "system_rebuild_normal_iops_write": 0,
+ "system_rebuild_normal_pending_capacity_in_Kb": 0,
+ "system_rebuild_total_bandwidth_read": 0,
+ "system_rebuild_total_bandwidth_read_write": 0,
+ "system_rebuild_total_bandwidth_write": 0,
+ "system_rebuild_total_io_size_read": 0,
+ "system_rebuild_total_io_size_read_write": 0,
+ "system_rebuild_total_io_size_write": 0,
+ "system_rebuild_total_iops_read": 0,
+ "system_rebuild_total_iops_read_write": 0,
+ "system_rebuild_total_iops_write": 0,
+ "system_rebuild_total_pending_capacity_in_Kb": 0,
+ "system_total_bandwidth_read": 800,
+ "system_total_bandwidth_read_write": 472608800,
+ "system_total_bandwidth_write": 472608000,
+ "system_total_io_size_read": 4000,
+ "system_total_io_size_read_write": 769729,
+ "system_total_io_size_write": 765729,
+ "system_total_iops_read": 200,
+ "system_total_iops_read_write": 617400,
+ "system_total_iops_write": 617200,
+ }
+
+ collected := scaleIO.Collect()
+ assert.Equal(t, expected, collected)
+ testCharts(t, scaleIO, collected)
+}
+
+func TestScaleIO_Collect_ConnectionRefused(t *testing.T) {
+ srv, _, scaleIO := prepareSrvMockScaleIO(t)
+ defer srv.Close()
+ require.NoError(t, scaleIO.Init())
+ require.NoError(t, scaleIO.Check())
+ scaleIO.client.Request.URL = "http://127.0.0.1:38001"
+
+ assert.Nil(t, scaleIO.Collect())
+}
+
+func testCharts(t *testing.T, scaleIO *ScaleIO, collected map[string]int64) {
+ t.Helper()
+ ensureStoragePoolChartsAreCreated(t, scaleIO)
+ ensureSdcChartsAreCreated(t, scaleIO)
+ ensureCollectedHasAllChartsDimsVarsIDs(t, scaleIO, collected)
+}
+
+func ensureStoragePoolChartsAreCreated(t *testing.T, scaleIO *ScaleIO) {
+ for _, pool := range scaleIO.discovered.pool {
+ for _, chart := range *newStoragePoolCharts(pool) {
+ assert.Truef(t, scaleIO.Charts().Has(chart.ID), "chart '%s' is not created", chart.ID)
+ }
+ }
+}
+
+func ensureSdcChartsAreCreated(t *testing.T, scaleIO *ScaleIO) {
+ for _, sdc := range scaleIO.discovered.sdc {
+ for _, chart := range *newSdcCharts(sdc) {
+ assert.Truef(t, scaleIO.Charts().Has(chart.ID), "chart '%s' is not created", chart.ID)
+ }
+ }
+}
+
+func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, scaleIO *ScaleIO, collected map[string]int64) {
+ for _, chart := range *scaleIO.Charts() {
+ for _, dim := range chart.Dims {
+ _, ok := collected[dim.ID]
+ assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID)
+ }
+ for _, v := range chart.Vars {
+ _, ok := collected[v.ID]
+ assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID)
+ }
+ }
+}
+
+func prepareSrvMockScaleIO(t *testing.T) (*httptest.Server, *client.MockScaleIOAPIServer, *ScaleIO) {
+ t.Helper()
+ const (
+ user = "user"
+ password = "password"
+ version = "2.5"
+ token = "token"
+ )
+ var stats client.SelectedStatistics
+ err := json.Unmarshal(dataSelectedStatistics, &stats)
+ require.NoError(t, err)
+
+ var ins client.Instances
+ err = json.Unmarshal(dataInstances, &ins)
+ require.NoError(t, err)
+
+ mock := client.MockScaleIOAPIServer{
+ User: user,
+ Password: password,
+ Version: version,
+ Token: token,
+ Instances: ins,
+ Statistics: stats,
+ }
+ srv := httptest.NewServer(&mock)
+ require.NoError(t, err)
+
+ scaleIO := New()
+ scaleIO.URL = srv.URL
+ scaleIO.Username = user
+ scaleIO.Password = password
+ return srv, &mock, scaleIO
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.json b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.json
new file mode 100644
index 000000000..984c3ed6e
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.json
@@ -0,0 +1,20 @@
+{
+ "update_every": 123,
+ "url": "ok",
+ "body": "ok",
+ "method": "ok",
+ "headers": {
+ "ok": "ok"
+ },
+ "username": "ok",
+ "password": "ok",
+ "proxy_url": "ok",
+ "proxy_username": "ok",
+ "proxy_password": "ok",
+ "timeout": 123.123,
+ "not_follow_redirects": true,
+ "tls_ca": "ok",
+ "tls_cert": "ok",
+ "tls_key": "ok",
+ "tls_skip_verify": true
+}
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.yaml b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.yaml
new file mode 100644
index 000000000..8558b61cc
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/config.yaml
@@ -0,0 +1,17 @@
+update_every: 123
+url: "ok"
+body: "ok"
+method: "ok"
+headers:
+ ok: "ok"
+username: "ok"
+password: "ok"
+proxy_url: "ok"
+proxy_username: "ok"
+proxy_password: "ok"
+timeout: 123.123
+not_follow_redirects: yes
+tls_ca: "ok"
+tls_cert: "ok"
+tls_key: "ok"
+tls_skip_verify: yes
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/testdata/instances.json b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/instances.json
new file mode 100644
index 000000000..bc8c6e8ac
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/instances.json
@@ -0,0 +1,1160 @@
+{
+ "System": {
+ "authenticationMethod": "Native",
+ "capacityAlertCriticalThresholdPercent": 90,
+ "capacityAlertHighThresholdPercent": 80,
+ "capacityTimeLeftInDays": "Unlimited",
+ "cliPasswordAllowed": true,
+ "daysInstalled": 17,
+ "defaultIsVolumeObfuscated": false,
+ "enterpriseFeaturesEnabled": true,
+ "id": "499634a44778afc0",
+ "installId": "3e9fc5811a7efb00",
+ "isInitialLicense": true,
+ "links": [
+ {
+ "href": "/api/instances/System::499634a44778afc0",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0/relationships/Statistics",
+ "rel": "/api/System/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0/relationships/ProtectionDomain",
+ "rel": "/api/System/relationship/ProtectionDomain"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0/relationships/Sdc",
+ "rel": "/api/System/relationship/Sdc"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0/relationships/User",
+ "rel": "/api/System/relationship/User"
+ }
+ ],
+ "managementClientSecureCommunicationEnabled": true,
+ "maxCapacityInGb": "Unlimited",
+ "mdmCluster": {
+ "clusterMode": "ThreeNodes",
+ "clusterState": "ClusteredNormal",
+ "goodNodesNum": 3,
+ "goodReplicasNum": 2,
+ "id": "5302483491453710272",
+ "master": {
+ "id": "65ed0ee3247d0a00",
+ "ips": [
+ "100.127.0.10"
+ ],
+ "managementIPs": [
+ "100.127.0.10"
+ ],
+ "name": "Manager1",
+ "opensslVersion": "OpenSSL 1.0.2g 1 Mar 2016",
+ "port": 9011,
+ "role": "Manager",
+ "versionInfo": "R2_6.11000.0",
+ "virtualInterfaces": []
+ },
+ "slaves": [
+ {
+ "id": "4cc44104130ce7b1",
+ "ips": [
+ "100.127.0.11"
+ ],
+ "managementIPs": [
+ "100.127.0.11"
+ ],
+ "name": "Manager2",
+ "opensslVersion": "OpenSSL 1.0.2g 1 Mar 2016",
+ "port": 9011,
+ "role": "Manager",
+ "status": "Normal",
+ "versionInfo": "R2_6.11000.0",
+ "virtualInterfaces": []
+ }
+ ],
+ "tieBreakers": [
+ {
+ "id": "35bf9d62661a6db2",
+ "ips": [
+ "100.127.0.12"
+ ],
+ "managementIPs": [
+ "100.127.0.12"
+ ],
+ "name": "Tie-Breaker1",
+ "opensslVersion": "N/A",
+ "port": 9011,
+ "role": "TieBreaker",
+ "status": "Normal",
+ "versionInfo": "R2_6.11000.0"
+ }
+ ]
+ },
+ "mdmManagementPort": 6611,
+ "mdmToSdsPolicy": "Authentication",
+ "perfProfile": "Default",
+ "remoteReadOnlyLimitState": false,
+ "restrictedSdcMode": "None",
+ "restrictedSdcModeEnabled": false,
+ "sdcLongOperationsCounterParameters": {
+ "longWindow": {
+ "threshold": 1000000,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 100000,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 10000,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdcMdmNetworkDisconnectionsCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdcMemoryAllocationFailuresCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdcSdsConnectivityInfo": {
+ "disconnectedSdcId": null,
+ "disconnectedSdcName": null,
+ "disconnectedSdsId": null,
+ "disconnectedSdsIp": null,
+ "disconnectedSdsName": null,
+ "sdcSdsConnectivityStatus": "AllConnected"
+ },
+ "sdcSdsNetworkDisconnectionsCounterParameters": {
+ "longWindow": {
+ "threshold": 20000,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 4000,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 800,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdcSocketAllocationFailuresCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "showGuid": true,
+ "swid": "",
+ "systemVersionName": "DellEMC ScaleIO Version: R2_6.11000.113",
+ "tlsVersion": "TLSv1.2",
+ "upgradeState": "NoUpgrade"
+ },
+ "deviceList": [
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 103808000,
+ "deviceCurrentPathName": "/dev/sdb",
+ "deviceOriginalPathName": "/dev/sdb",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbf9d6500010000",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbf9d6500010000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbf9d6500010000/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabe00000001",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 103808000,
+ "name": "sdb",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabe00000001",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "40395b7b00000000",
+ "temperatureState": "NeverFailed"
+ },
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 114293760,
+ "deviceCurrentPathName": "/dev/sdc",
+ "deviceOriginalPathName": "/dev/sdc",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbfc47300010001",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbfc47300010001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbfc47300010001/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabe00000001",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 114293760,
+ "name": "sdc",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabe00000001",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "4039828b00000001",
+ "temperatureState": "NeverFailed"
+ },
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 103808000,
+ "deviceCurrentPathName": "/dev/sdb",
+ "deviceOriginalPathName": "/dev/sdb",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbd9d6400000000",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbd9d6400000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbd9d6400000000/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabd00000000",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 103808000,
+ "name": "sdb",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabd00000000",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "40395b7b00000000",
+ "temperatureState": "NeverFailed"
+ },
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 114293760,
+ "deviceCurrentPathName": "/dev/sdc",
+ "deviceOriginalPathName": "/dev/sdc",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbfc47700020001",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbfc47700020001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbfc47700020001/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabf00000002",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 114293760,
+ "name": "sdc",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabf00000002",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "4039828b00000001",
+ "temperatureState": "NeverFailed"
+ },
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 103808000,
+ "deviceCurrentPathName": "/dev/sdc",
+ "deviceOriginalPathName": "/dev/sdc",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbdc47600000001",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbdc47600000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbdc47600000001/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabd00000000",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 103808000,
+ "name": "sdc",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabd00000000",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "40395b7b00000000",
+ "temperatureState": "NeverFailed"
+ },
+ {
+ "aggregatedState": "NeverFailed",
+ "capacityLimitInKb": 103808000,
+ "deviceCurrentPathName": "/dev/sdb",
+ "deviceOriginalPathName": "/dev/sdb",
+ "deviceState": "Normal",
+ "errorState": "None",
+ "id": "ebbfc47800020000",
+ "ledSetting": "Off",
+ "links": [
+ {
+ "href": "/api/instances/Device::ebbfc47800020000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Device::ebbfc47800020000/relationships/Statistics",
+ "rel": "/api/Device/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabf00000002",
+ "rel": "/api/parent/relationship/sdsId"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "longSuccessfulIos": {
+ "longWindow": null,
+ "mediumWindow": null,
+ "shortWindow": null
+ },
+ "maxCapacityInKb": 103808000,
+ "name": "sdb",
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "sdsId": "130dcabf00000002",
+ "ssdEndOfLifeState": "NeverFailed",
+ "storagePoolId": "4039828b00000001",
+ "temperatureState": "NeverFailed"
+ }
+ ],
+ "faultSetList": [
+ {
+ "id": "a6a7b4cf00000000",
+ "links": [
+ {
+ "href": "/api/instances/FaultSet::a6a7b4cf00000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/FaultSet::a6a7b4cf00000000/relationships/Statistics",
+ "rel": "/api/FaultSet/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/FaultSet::a6a7b4cf00000000/relationships/Sds",
+ "rel": "/api/FaultSet/relationship/Sds"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "name": "MyFaultSet",
+ "protectionDomainId": "74d855a900000000"
+ }
+ ],
+ "isDirty": false,
+ "lastDeviceVersion": 47,
+ "lastFaultSetVersion": 2,
+ "lastProtectionDomainVersion": 2,
+ "lastRfcacheDeviceVersion": 1,
+ "lastSdcVersion": 7,
+ "lastSdsVersion": 19,
+ "lastStoragePoolVersion": 4,
+ "lastSystemVersion": 2,
+ "lastVTreeVersion": 3,
+ "lastVolumeVersion": 3,
+ "protectionDomainList": [
+ {
+ "id": "74d855a900000000",
+ "links": [
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000/relationships/Statistics",
+ "rel": "/api/ProtectionDomain/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000/relationships/StoragePool",
+ "rel": "/api/ProtectionDomain/relationship/StoragePool"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000/relationships/Sds",
+ "rel": "/api/ProtectionDomain/relationship/Sds"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000/relationships/FaultSet",
+ "rel": "/api/ProtectionDomain/relationship/FaultSet"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0",
+ "rel": "/api/parent/relationship/systemId"
+ }
+ ],
+ "mdmSdsNetworkDisconnectionsCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "name": "default",
+ "overallIoNetworkThrottlingEnabled": false,
+ "overallIoNetworkThrottlingInKbps": null,
+ "protectionDomainState": "Active",
+ "rebalanceNetworkThrottlingEnabled": false,
+ "rebalanceNetworkThrottlingInKbps": null,
+ "rebuildNetworkThrottlingEnabled": false,
+ "rebuildNetworkThrottlingInKbps": null,
+ "rfcacheEnabled": true,
+ "rfcacheMaxIoSizeKb": 128,
+ "rfcacheOpertionalMode": "WriteMiss",
+ "rfcachePageSizeKb": 64,
+ "sdsConfigurationFailureCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdsDecoupledCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdsReceiveBufferAllocationFailuresCounterParameters": {
+ "longWindow": {
+ "threshold": 2000000,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 200000,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 20000,
+ "windowSizeInSec": 60
+ }
+ },
+ "sdsSdsNetworkDisconnectionsCounterParameters": {
+ "longWindow": {
+ "threshold": 700,
+ "windowSizeInSec": 86400
+ },
+ "mediumWindow": {
+ "threshold": 500,
+ "windowSizeInSec": 3600
+ },
+ "shortWindow": {
+ "threshold": 300,
+ "windowSizeInSec": 60
+ }
+ },
+ "systemId": "499634a44778afc0"
+ }
+ ],
+ "rfcacheDeviceList": null,
+ "sdcList": [
+ {
+ "id": "6076fd1100000002",
+ "installedSoftwareVersionInfo": "R2_6.11000.0",
+ "kernelBuildNumber": null,
+ "kernelVersion": "4.15.18",
+ "links": [
+ {
+ "href": "/api/instances/Sdc::6076fd1100000002",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd1100000002/relationships/Statistics",
+ "rel": "/api/Sdc/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd1100000002/relationships/Volume",
+ "rel": "/api/Sdc/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0",
+ "rel": "/api/parent/relationship/systemId"
+ }
+ ],
+ "mdmConnectionState": "Disconnected",
+ "memoryAllocationFailure": null,
+ "name": null,
+ "osType": "Linux",
+ "perfProfile": "Default",
+ "sdcApproved": true,
+ "sdcApprovedIps": [
+ "100.127.0.12"
+ ],
+ "sdcGuid": "B71F01AE-FF7A-47C5-A303-583FFD416818",
+ "sdcIp": "100.127.0.12",
+ "socketAllocationFailure": null,
+ "softwareVersionInfo": null,
+ "systemId": "499634a44778afc0",
+ "versionInfo": null
+ },
+ {
+ "id": "6076fd1000000001",
+ "installedSoftwareVersionInfo": "R2_6.11000.0",
+ "kernelBuildNumber": null,
+ "kernelVersion": "4.15.18",
+ "links": [
+ {
+ "href": "/api/instances/Sdc::6076fd1000000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd1000000001/relationships/Statistics",
+ "rel": "/api/Sdc/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd1000000001/relationships/Volume",
+ "rel": "/api/Sdc/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0",
+ "rel": "/api/parent/relationship/systemId"
+ }
+ ],
+ "mdmConnectionState": "Disconnected",
+ "memoryAllocationFailure": null,
+ "name": null,
+ "osType": "Linux",
+ "perfProfile": "Default",
+ "sdcApproved": true,
+ "sdcApprovedIps": [
+ "100.127.0.11"
+ ],
+ "sdcGuid": "5D2B24F9-5D49-4688-A67D-88AF8790BC05",
+ "sdcIp": "100.127.0.11",
+ "socketAllocationFailure": null,
+ "softwareVersionInfo": null,
+ "systemId": "499634a44778afc0",
+ "versionInfo": null
+ },
+ {
+ "id": "6076fd0f00000000",
+ "installedSoftwareVersionInfo": "R2_6.11000.0",
+ "kernelBuildNumber": null,
+ "kernelVersion": "4.15.18",
+ "links": [
+ {
+ "href": "/api/instances/Sdc::6076fd0f00000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd0f00000000/relationships/Statistics",
+ "rel": "/api/Sdc/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sdc::6076fd0f00000000/relationships/Volume",
+ "rel": "/api/Sdc/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/System::499634a44778afc0",
+ "rel": "/api/parent/relationship/systemId"
+ }
+ ],
+ "mdmConnectionState": "Connected",
+ "memoryAllocationFailure": null,
+ "name": null,
+ "osType": "Linux",
+ "perfProfile": "Default",
+ "sdcApproved": true,
+ "sdcApprovedIps": [
+ "100.127.0.10"
+ ],
+ "sdcGuid": "974F4AC7-FF37-4909-8713-D1BD3F002843",
+ "sdcIp": "100.127.0.10",
+ "socketAllocationFailure": null,
+ "softwareVersionInfo": "R2_6.11000.0",
+ "systemId": "499634a44778afc0",
+ "versionInfo": "R2_6.11000.0"
+ }
+ ],
+ "sdsList": [
+ {
+ "authenticationError": "None",
+ "certificateInfo": {
+ "issuer": "/GN=MDM/CN=test-VirtualBox/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "subject": "/GN=SDS-000/CN=scaleIOslave1/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "thumbprint": "FD:00:99:E9:40:90:A5:CE:85:B8:A9:07:86:BB:7E:F0:E0:DE:F9:75",
+ "validFrom": "Nov 12 19:17:22 2019 GMT",
+ "validFromAsn1Format": "191112191722Z",
+ "validTo": "Nov 10 20:17:22 2029 GMT",
+ "validToAsn1Format": "291110201722Z"
+ },
+ "drlMode": "Volatile",
+ "faultSetId": null,
+ "id": "130dcabd00000000",
+ "ipList": [
+ {
+ "ip": "100.127.0.11",
+ "role": "all"
+ }
+ ],
+ "links": [
+ {
+ "href": "/api/instances/Sds::130dcabd00000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabd00000000/relationships/Statistics",
+ "rel": "/api/Sds/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabd00000000/relationships/Device",
+ "rel": "/api/Sds/relationship/Device"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabd00000000/relationships/RfcacheDevice",
+ "rel": "/api/Sds/relationship/RfcacheDevice"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "maintenanceState": "NoMaintenance",
+ "mdmConnectionState": "Connected",
+ "membershipState": "Joined",
+ "name": "SDS_[100.127.0.11]",
+ "numOfIoBuffers": null,
+ "onVmWare": false,
+ "perfProfile": "Default",
+ "port": 7072,
+ "protectionDomainId": "74d855a900000000",
+ "rfcacheEnabled": true,
+ "rfcacheErrorApiVersionMismatch": false,
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "rfcacheErrorInconsistentCacheConfiguration": false,
+ "rfcacheErrorInconsistentSourceConfiguration": false,
+ "rfcacheErrorInvalidDriverPath": false,
+ "rfcacheErrorLowResources": false,
+ "rmcacheEnabled": true,
+ "rmcacheFrozen": false,
+ "rmcacheMemoryAllocationState": "AllocationPending",
+ "rmcacheSizeInKb": 131072,
+ "sdsConfigurationFailure": null,
+ "sdsDecoupled": null,
+ "sdsReceiveBufferAllocationFailures": null,
+ "sdsState": "Normal",
+ "softwareVersionInfo": "R2_6.11000.0"
+ },
+ {
+ "authenticationError": "None",
+ "certificateInfo": {
+ "issuer": "/GN=MDM/CN=test-VirtualBox/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "subject": "/GN=SDS-001/CN=test-VirtualBox/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "thumbprint": "B2:F9:88:84:55:94:A1:D8:7F:C1:4F:50:81:17:56:AC:72:B7:A2:AD",
+ "validFrom": "Nov 12 19:17:22 2019 GMT",
+ "validFromAsn1Format": "191112191722Z",
+ "validTo": "Nov 10 20:17:22 2029 GMT",
+ "validToAsn1Format": "291110201722Z"
+ },
+ "drlMode": "Volatile",
+ "faultSetId": null,
+ "id": "130dcabe00000001",
+ "ipList": [
+ {
+ "ip": "100.127.0.10",
+ "role": "all"
+ }
+ ],
+ "links": [
+ {
+ "href": "/api/instances/Sds::130dcabe00000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabe00000001/relationships/Statistics",
+ "rel": "/api/Sds/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabe00000001/relationships/Device",
+ "rel": "/api/Sds/relationship/Device"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabe00000001/relationships/RfcacheDevice",
+ "rel": "/api/Sds/relationship/RfcacheDevice"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "maintenanceState": "NoMaintenance",
+ "mdmConnectionState": "Connected",
+ "membershipState": "Joined",
+ "name": "SDS_[100.127.0.10]",
+ "numOfIoBuffers": null,
+ "onVmWare": false,
+ "perfProfile": "Default",
+ "port": 7072,
+ "protectionDomainId": "74d855a900000000",
+ "rfcacheEnabled": true,
+ "rfcacheErrorApiVersionMismatch": false,
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "rfcacheErrorInconsistentCacheConfiguration": false,
+ "rfcacheErrorInconsistentSourceConfiguration": false,
+ "rfcacheErrorInvalidDriverPath": false,
+ "rfcacheErrorLowResources": false,
+ "rmcacheEnabled": true,
+ "rmcacheFrozen": false,
+ "rmcacheMemoryAllocationState": "AllocationPending",
+ "rmcacheSizeInKb": 131072,
+ "sdsConfigurationFailure": null,
+ "sdsDecoupled": null,
+ "sdsReceiveBufferAllocationFailures": null,
+ "sdsState": "Normal",
+ "softwareVersionInfo": "R2_6.11000.0"
+ },
+ {
+ "authenticationError": "None",
+ "certificateInfo": {
+ "issuer": "/GN=MDM/CN=test-VirtualBox/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "subject": "/GN=SDS-002/CN=scaleIOSlave2/L=Hopkinton/ST=Massachusetts/C=US/O=EMC/OU=ASD",
+ "thumbprint": "CC:A0:E8:B7:84:9B:E5:D1:2E:F6:7C:3A:AC:21:D6:5C:5F:D1:47:D1",
+ "validFrom": "Nov 12 19:17:21 2019 GMT",
+ "validFromAsn1Format": "191112191721Z",
+ "validTo": "Nov 10 20:17:21 2029 GMT",
+ "validToAsn1Format": "291110201721Z"
+ },
+ "drlMode": "Volatile",
+ "faultSetId": null,
+ "id": "130dcabf00000002",
+ "ipList": [
+ {
+ "ip": "100.127.0.12",
+ "role": "all"
+ }
+ ],
+ "links": [
+ {
+ "href": "/api/instances/Sds::130dcabf00000002",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabf00000002/relationships/Statistics",
+ "rel": "/api/Sds/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabf00000002/relationships/Device",
+ "rel": "/api/Sds/relationship/Device"
+ },
+ {
+ "href": "/api/instances/Sds::130dcabf00000002/relationships/RfcacheDevice",
+ "rel": "/api/Sds/relationship/RfcacheDevice"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "maintenanceState": "NoMaintenance",
+ "mdmConnectionState": "Connected",
+ "membershipState": "Joined",
+ "name": "SDS_[100.127.0.12]",
+ "numOfIoBuffers": null,
+ "onVmWare": false,
+ "perfProfile": "Default",
+ "port": 7072,
+ "protectionDomainId": "74d855a900000000",
+ "rfcacheEnabled": true,
+ "rfcacheErrorApiVersionMismatch": false,
+ "rfcacheErrorDeviceDoesNotExist": false,
+ "rfcacheErrorInconsistentCacheConfiguration": false,
+ "rfcacheErrorInconsistentSourceConfiguration": false,
+ "rfcacheErrorInvalidDriverPath": false,
+ "rfcacheErrorLowResources": false,
+ "rmcacheEnabled": true,
+ "rmcacheFrozen": false,
+ "rmcacheMemoryAllocationState": "AllocationPending",
+ "rmcacheSizeInKb": 131072,
+ "sdsConfigurationFailure": null,
+ "sdsDecoupled": null,
+ "sdsReceiveBufferAllocationFailures": null,
+ "sdsState": "Normal",
+ "softwareVersionInfo": "R2_6.11000.0"
+ }
+ ],
+ "sessionTag": 19,
+ "storagePoolList": [
+ {
+ "backgroundScannerBWLimitKBps": 0,
+ "backgroundScannerMode": "Disabled",
+ "capacityAlertCriticalThreshold": 90,
+ "capacityAlertHighThreshold": 80,
+ "checksumEnabled": false,
+ "id": "4039828b00000001",
+ "links": [
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001/relationships/Statistics",
+ "rel": "/api/StoragePool/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001/relationships/Volume",
+ "rel": "/api/StoragePool/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001/relationships/Device",
+ "rel": "/api/StoragePool/relationship/Device"
+ },
+ {
+ "href": "/api/instances/StoragePool::4039828b00000001/relationships/VTree",
+ "rel": "/api/StoragePool/relationship/VTree"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "name": "StoragePool2",
+ "numOfParallelRebuildRebalanceJobsPerDevice": 2,
+ "protectionDomainId": "74d855a900000000",
+ "rebalanceEnabled": true,
+ "rebalanceIoPriorityAppBwPerDeviceThresholdInKbps": null,
+ "rebalanceIoPriorityAppIopsPerDeviceThreshold": null,
+ "rebalanceIoPriorityBwLimitPerDeviceInKbps": 10240,
+ "rebalanceIoPriorityNumOfConcurrentIosPerDevice": 1,
+ "rebalanceIoPriorityPolicy": "favorAppIos",
+ "rebalanceIoPriorityQuietPeriodInMsec": null,
+ "rebuildEnabled": true,
+ "rebuildIoPriorityAppBwPerDeviceThresholdInKbps": null,
+ "rebuildIoPriorityAppIopsPerDeviceThreshold": null,
+ "rebuildIoPriorityBwLimitPerDeviceInKbps": 10240,
+ "rebuildIoPriorityNumOfConcurrentIosPerDevice": 1,
+ "rebuildIoPriorityPolicy": "limitNumOfConcurrentIos",
+ "rebuildIoPriorityQuietPeriodInMsec": null,
+ "rmcacheWriteHandlingMode": "Cached",
+ "sparePercentage": 10,
+ "useRfcache": false,
+ "useRmcache": false,
+ "zeroPaddingEnabled": false
+ },
+ {
+ "backgroundScannerBWLimitKBps": 0,
+ "backgroundScannerMode": "Disabled",
+ "capacityAlertCriticalThreshold": 90,
+ "capacityAlertHighThreshold": 80,
+ "checksumEnabled": false,
+ "id": "40395b7b00000000",
+ "links": [
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000/relationships/Statistics",
+ "rel": "/api/StoragePool/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000/relationships/Volume",
+ "rel": "/api/StoragePool/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000/relationships/Device",
+ "rel": "/api/StoragePool/relationship/Device"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000/relationships/VTree",
+ "rel": "/api/StoragePool/relationship/VTree"
+ },
+ {
+ "href": "/api/instances/ProtectionDomain::74d855a900000000",
+ "rel": "/api/parent/relationship/protectionDomainId"
+ }
+ ],
+ "name": "StoragePool1",
+ "numOfParallelRebuildRebalanceJobsPerDevice": 2,
+ "protectionDomainId": "74d855a900000000",
+ "rebalanceEnabled": true,
+ "rebalanceIoPriorityAppBwPerDeviceThresholdInKbps": null,
+ "rebalanceIoPriorityAppIopsPerDeviceThreshold": null,
+ "rebalanceIoPriorityBwLimitPerDeviceInKbps": 10240,
+ "rebalanceIoPriorityNumOfConcurrentIosPerDevice": 1,
+ "rebalanceIoPriorityPolicy": "favorAppIos",
+ "rebalanceIoPriorityQuietPeriodInMsec": null,
+ "rebuildEnabled": true,
+ "rebuildIoPriorityAppBwPerDeviceThresholdInKbps": null,
+ "rebuildIoPriorityAppIopsPerDeviceThreshold": null,
+ "rebuildIoPriorityBwLimitPerDeviceInKbps": 10240,
+ "rebuildIoPriorityNumOfConcurrentIosPerDevice": 1,
+ "rebuildIoPriorityPolicy": "limitNumOfConcurrentIos",
+ "rebuildIoPriorityQuietPeriodInMsec": null,
+ "rmcacheWriteHandlingMode": "Cached",
+ "sparePercentage": 10,
+ "useRfcache": false,
+ "useRmcache": false,
+ "zeroPaddingEnabled": false
+ }
+ ],
+ "vTreeList": [
+ {
+ "baseVolumeId": "993a355e00000001",
+ "id": "252fd6e400000001",
+ "links": [
+ {
+ "href": "/api/instances/VTree::252fd6e400000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e400000001/relationships/Statistics",
+ "rel": "/api/VTree/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e400000001/relationships/Volume",
+ "rel": "/api/VTree/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/Volume::993a355e00000001",
+ "rel": "/api/parent/relationship/baseVolumeId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "name": null,
+ "storagePoolId": "40395b7b00000000"
+ },
+ {
+ "baseVolumeId": "993a355d00000000",
+ "id": "252fd6e300000000",
+ "links": [
+ {
+ "href": "/api/instances/VTree::252fd6e300000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e300000000/relationships/Statistics",
+ "rel": "/api/VTree/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e300000000/relationships/Volume",
+ "rel": "/api/VTree/relationship/Volume"
+ },
+ {
+ "href": "/api/instances/Volume::993a355d00000000",
+ "rel": "/api/parent/relationship/baseVolumeId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "name": null,
+ "storagePoolId": "40395b7b00000000"
+ }
+ ],
+ "volumeList": [
+ {
+ "ancestorVolumeId": null,
+ "consistencyGroupId": null,
+ "creationTime": 1574882772,
+ "id": "993a355e00000001",
+ "isObfuscated": false,
+ "isVvol": false,
+ "links": [
+ {
+ "href": "/api/instances/Volume::993a355e00000001",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Volume::993a355e00000001/relationships/Statistics",
+ "rel": "/api/Volume/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e400000001",
+ "rel": "/api/parent/relationship/vtreeId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "mappedSdcInfo": [
+ {
+ "limitBwInMbps": 0,
+ "limitIops": 0,
+ "sdcId": "6076fd1100000002",
+ "sdcIp": "100.127.0.12"
+ }
+ ],
+ "mappingToAllSdcsEnabled": false,
+ "name": "volume2-16",
+ "sizeInKb": 16777216,
+ "storagePoolId": "40395b7b00000000",
+ "useRmcache": false,
+ "volumeType": "ThinProvisioned",
+ "vtreeId": "252fd6e400000001"
+ },
+ {
+ "ancestorVolumeId": null,
+ "consistencyGroupId": null,
+ "creationTime": 1574882580,
+ "id": "993a355d00000000",
+ "isObfuscated": false,
+ "isVvol": false,
+ "links": [
+ {
+ "href": "/api/instances/Volume::993a355d00000000",
+ "rel": "self"
+ },
+ {
+ "href": "/api/instances/Volume::993a355d00000000/relationships/Statistics",
+ "rel": "/api/Volume/relationship/Statistics"
+ },
+ {
+ "href": "/api/instances/VTree::252fd6e300000000",
+ "rel": "/api/parent/relationship/vtreeId"
+ },
+ {
+ "href": "/api/instances/StoragePool::40395b7b00000000",
+ "rel": "/api/parent/relationship/storagePoolId"
+ }
+ ],
+ "mappedSdcInfo": [
+ {
+ "limitBwInMbps": 0,
+ "limitIops": 0,
+ "sdcId": "6076fd1000000001",
+ "sdcIp": "100.127.0.11"
+ }
+ ],
+ "mappingToAllSdcsEnabled": false,
+ "name": "volume1-16",
+ "sizeInKb": 16777216,
+ "storagePoolId": "40395b7b00000000",
+ "useRmcache": false,
+ "volumeType": "ThinProvisioned",
+ "vtreeId": "252fd6e300000000"
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/go/collectors/go.d.plugin/modules/scaleio/testdata/selected_statistics.json b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/selected_statistics.json
new file mode 100644
index 000000000..0b141bbe6
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/scaleio/testdata/selected_statistics.json
@@ -0,0 +1,777 @@
+{
+ "Sdc": {
+ "6076fd0f00000000": {
+ "numOfMappedVolumes": 1,
+ "userDataReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 1,
+ "totalWeightInKb": 0
+ },
+ "userDataWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 1,
+ "totalWeightInKb": 0
+ },
+ "volumeIds": [
+ "993a5c6d00000002"
+ ]
+ },
+ "6076fd1000000001": {
+ "numOfMappedVolumes": 1,
+ "userDataReadBwc": {
+ "numOccured": 1,
+ "numSeconds": 1,
+ "totalWeightInKb": 1
+ },
+ "userDataWriteBwc": {
+ "numOccured": 169,
+ "numSeconds": 1,
+ "totalWeightInKb": 117399
+ },
+ "volumeIds": [
+ "993a355d00000000"
+ ]
+ },
+ "6076fd1100000002": {
+ "numOfMappedVolumes": 1,
+ "userDataReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 1,
+ "totalWeightInKb": 0
+ },
+ "userDataWriteBwc": {
+ "numOccured": 145,
+ "numSeconds": 1,
+ "totalWeightInKb": 118972
+ },
+ "volumeIds": [
+ "993a355e00000001"
+ ]
+ }
+ },
+ "StoragePool": {
+ "40395b7b00000000": {
+ "BackgroundScanCompareCount": 0,
+ "BackgroundScannedInMB": 0,
+ "activeBckRebuildCapacityInKb": 0,
+ "activeFwdRebuildCapacityInKb": 0,
+ "activeMovingCapacityInKb": 0,
+ "activeMovingInBckRebuildJobs": 0,
+ "activeMovingInFwdRebuildJobs": 0,
+ "activeMovingInNormRebuildJobs": 0,
+ "activeMovingInRebalanceJobs": 0,
+ "activeMovingOutBckRebuildJobs": 0,
+ "activeMovingOutFwdRebuildJobs": 0,
+ "activeMovingOutNormRebuildJobs": 0,
+ "activeMovingRebalanceJobs": 0,
+ "activeNormRebuildCapacityInKb": 0,
+ "activeRebalanceCapacityInKb": 0,
+ "atRestCapacityInKb": 50110464,
+ "bckRebuildCapacityInKb": 0,
+ "bckRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "bckRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "capacityAvailableForVolumeAllocationInKb": 100663296,
+ "capacityInUseInKb": 50110464,
+ "capacityLimitInKb": 311424000,
+ "degradedFailedCapacityInKb": 0,
+ "degradedFailedVacInKb": 0,
+ "degradedHealthyCapacityInKb": 0,
+ "degradedHealthyVacInKb": 0,
+ "deviceIds": [
+ "ebbdc47a00000000",
+ "ebbf9d6500010000",
+ "ebbfc47900020000"
+ ],
+ "failedCapacityInKb": 0,
+ "failedVacInKb": 0,
+ "fixedReadErrorCount": 0,
+ "fwdRebuildCapacityInKb": 0,
+ "fwdRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "fwdRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "inMaintenanceCapacityInKb": 0,
+ "inMaintenanceVacInKb": 0,
+ "inUseVacInKb": 67108864,
+ "maxCapacityInKb": 311424000,
+ "movingCapacityInKb": 0,
+ "normRebuildCapacityInKb": 0,
+ "normRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "normRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "numOfDevices": 3,
+ "numOfMappedToAllVolumes": 0,
+ "numOfSnapshots": 1,
+ "numOfThickBaseVolumes": 0,
+ "numOfThinBaseVolumes": 2,
+ "numOfUnmappedVolumes": 0,
+ "numOfVolumes": 3,
+ "numOfVolumesInDeletion": 0,
+ "numOfVtrees": 2,
+ "pendingBckRebuildCapacityInKb": 0,
+ "pendingFwdRebuildCapacityInKb": 0,
+ "pendingMovingCapacityInKb": 0,
+ "pendingMovingInBckRebuildJobs": 0,
+ "pendingMovingInFwdRebuildJobs": 0,
+ "pendingMovingInNormRebuildJobs": 0,
+ "pendingMovingInRebalanceJobs": 0,
+ "pendingMovingOutBckRebuildJobs": 0,
+ "pendingMovingOutFwdRebuildJobs": 0,
+ "pendingMovingOutNormrebuildJobs": 0,
+ "pendingMovingRebalanceJobs": 0,
+ "pendingNormRebuildCapacityInKb": 0,
+ "pendingRebalanceCapacityInKb": 0,
+ "primaryReadBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "primaryReadFromDevBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "primaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "primaryVacInKb": 33554432,
+ "primaryWriteBwc": {
+ "numOccured": 1556,
+ "numSeconds": 5,
+ "totalWeightInKb": 1193408
+ },
+ "protectedCapacityInKb": 50110464,
+ "protectedVacInKb": 67108864,
+ "rebalanceCapacityInKb": 0,
+ "rebalanceReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rebalanceWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rfacheReadHit": 0,
+ "rfacheWriteHit": 0,
+ "rfcacheAvgReadTime": 0,
+ "rfcacheAvgWriteTime": 0,
+ "rfcacheIoErrors": 0,
+ "rfcacheIosOutstanding": 0,
+ "rfcacheIosSkipped": 0,
+ "rfcacheReadMiss": 0,
+ "rfcacheReadsFromCache": 0,
+ "rfcacheReadsPending": 0,
+ "rfcacheReadsReceived": 0,
+ "rfcacheReadsSkipped": 0,
+ "rfcacheReadsSkippedAlignedSizeTooLarge": 0,
+ "rfcacheReadsSkippedHeavyLoad": 0,
+ "rfcacheReadsSkippedInternalError": 0,
+ "rfcacheReadsSkippedLockIos": 0,
+ "rfcacheReadsSkippedLowResources": 0,
+ "rfcacheReadsSkippedMaxIoSize": 0,
+ "rfcacheReadsSkippedStuckIo": 0,
+ "rfcacheSkippedUnlinedWrite": 0,
+ "rfcacheSourceDeviceReads": 0,
+ "rfcacheSourceDeviceWrites": 0,
+ "rfcacheWriteMiss": 0,
+ "rfcacheWritePending": 0,
+ "rfcacheWritesReceived": 0,
+ "rfcacheWritesSkippedCacheMiss": 0,
+ "rfcacheWritesSkippedHeavyLoad": 0,
+ "rfcacheWritesSkippedInternalError": 0,
+ "rfcacheWritesSkippedLowResources": 0,
+ "rfcacheWritesSkippedMaxIoSize": 0,
+ "rfcacheWritesSkippedStuckIo": 0,
+ "rmPendingAllocatedInKb": 0,
+ "secondaryReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromDevBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryVacInKb": 33554432,
+ "secondaryWriteBwc": {
+ "numOccured": 1530,
+ "numSeconds": 5,
+ "totalWeightInKb": 1169632
+ },
+ "semiProtectedCapacityInKb": 0,
+ "semiProtectedVacInKb": 0,
+ "snapCapacityInUseInKb": 16699392,
+ "snapCapacityInUseOccupiedInKb": 749568,
+ "spareCapacityInKb": 31141888,
+ "thickCapacityInUseInKb": 0,
+ "thinCapacityAllocatedInKb": 67108864,
+ "thinCapacityInUseInKb": 49360896,
+ "totalReadBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "totalWriteBwc": {
+ "numOccured": 3086,
+ "numSeconds": 5,
+ "totalWeightInKb": 2363040
+ },
+ "unreachableUnusedCapacityInKb": 0,
+ "unusedCapacityInKb": 230171648,
+ "userDataReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "userDataWriteBwc": {
+ "numOccured": 285,
+ "numSeconds": 1,
+ "totalWeightInKb": 227170
+ },
+ "volumeIds": [
+ "993a355d00000000",
+ "993a5c6d00000002",
+ "993a355e00000001"
+ ],
+ "vtreeIds": [
+ "252fd6e300000000",
+ "252fd6e400000001"
+ ]
+ },
+ "4039828b00000001": {
+ "BackgroundScanCompareCount": 0,
+ "BackgroundScannedInMB": 0,
+ "activeBckRebuildCapacityInKb": 0,
+ "activeFwdRebuildCapacityInKb": 0,
+ "activeMovingCapacityInKb": 0,
+ "activeMovingInBckRebuildJobs": 0,
+ "activeMovingInFwdRebuildJobs": 0,
+ "activeMovingInNormRebuildJobs": 0,
+ "activeMovingInRebalanceJobs": 0,
+ "activeMovingOutBckRebuildJobs": 0,
+ "activeMovingOutFwdRebuildJobs": 0,
+ "activeMovingOutNormRebuildJobs": 0,
+ "activeMovingRebalanceJobs": 0,
+ "activeNormRebuildCapacityInKb": 0,
+ "activeRebalanceCapacityInKb": 0,
+ "atRestCapacityInKb": 0,
+ "bckRebuildCapacityInKb": 0,
+ "bckRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "bckRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "capacityAvailableForVolumeAllocationInKb": 142606336,
+ "capacityInUseInKb": 0,
+ "capacityLimitInKb": 332395520,
+ "degradedFailedCapacityInKb": 0,
+ "degradedFailedVacInKb": 0,
+ "degradedHealthyCapacityInKb": 0,
+ "degradedHealthyVacInKb": 0,
+ "deviceIds": [
+ "ebbdc47b00000001",
+ "ebbfc47300010001",
+ "ebbfc47700020001"
+ ],
+ "failedCapacityInKb": 0,
+ "failedVacInKb": 0,
+ "fixedReadErrorCount": 0,
+ "fwdRebuildCapacityInKb": 0,
+ "fwdRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "fwdRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "inMaintenanceCapacityInKb": 0,
+ "inMaintenanceVacInKb": 0,
+ "inUseVacInKb": 0,
+ "maxCapacityInKb": 332395520,
+ "movingCapacityInKb": 0,
+ "normRebuildCapacityInKb": 0,
+ "normRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "normRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "numOfDevices": 3,
+ "numOfMappedToAllVolumes": 0,
+ "numOfSnapshots": 0,
+ "numOfThickBaseVolumes": 0,
+ "numOfThinBaseVolumes": 0,
+ "numOfUnmappedVolumes": 0,
+ "numOfVolumes": 0,
+ "numOfVolumesInDeletion": 0,
+ "numOfVtrees": 0,
+ "pendingBckRebuildCapacityInKb": 0,
+ "pendingFwdRebuildCapacityInKb": 0,
+ "pendingMovingCapacityInKb": 0,
+ "pendingMovingInBckRebuildJobs": 0,
+ "pendingMovingInFwdRebuildJobs": 0,
+ "pendingMovingInNormRebuildJobs": 0,
+ "pendingMovingInRebalanceJobs": 0,
+ "pendingMovingOutBckRebuildJobs": 0,
+ "pendingMovingOutFwdRebuildJobs": 0,
+ "pendingMovingOutNormrebuildJobs": 0,
+ "pendingMovingRebalanceJobs": 0,
+ "pendingNormRebuildCapacityInKb": 0,
+ "pendingRebalanceCapacityInKb": 0,
+ "primaryReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "primaryReadFromDevBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "primaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "primaryVacInKb": 0,
+ "primaryWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "protectedCapacityInKb": 0,
+ "protectedVacInKb": 0,
+ "rebalanceCapacityInKb": 0,
+ "rebalanceReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rebalanceWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rfacheReadHit": 0,
+ "rfacheWriteHit": 0,
+ "rfcacheAvgReadTime": 0,
+ "rfcacheAvgWriteTime": 0,
+ "rfcacheIoErrors": 0,
+ "rfcacheIosOutstanding": 0,
+ "rfcacheIosSkipped": 0,
+ "rfcacheReadMiss": 0,
+ "rfcacheReadsFromCache": 0,
+ "rfcacheReadsPending": 0,
+ "rfcacheReadsReceived": 0,
+ "rfcacheReadsSkipped": 0,
+ "rfcacheReadsSkippedAlignedSizeTooLarge": 0,
+ "rfcacheReadsSkippedHeavyLoad": 0,
+ "rfcacheReadsSkippedInternalError": 0,
+ "rfcacheReadsSkippedLockIos": 0,
+ "rfcacheReadsSkippedLowResources": 0,
+ "rfcacheReadsSkippedMaxIoSize": 0,
+ "rfcacheReadsSkippedStuckIo": 0,
+ "rfcacheSkippedUnlinedWrite": 0,
+ "rfcacheSourceDeviceReads": 0,
+ "rfcacheSourceDeviceWrites": 0,
+ "rfcacheWriteMiss": 0,
+ "rfcacheWritePending": 0,
+ "rfcacheWritesReceived": 0,
+ "rfcacheWritesSkippedCacheMiss": 0,
+ "rfcacheWritesSkippedHeavyLoad": 0,
+ "rfcacheWritesSkippedInternalError": 0,
+ "rfcacheWritesSkippedLowResources": 0,
+ "rfcacheWritesSkippedMaxIoSize": 0,
+ "rfcacheWritesSkippedStuckIo": 0,
+ "rmPendingAllocatedInKb": 0,
+ "secondaryReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromDevBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryVacInKb": 0,
+ "secondaryWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "semiProtectedCapacityInKb": 0,
+ "semiProtectedVacInKb": 0,
+ "snapCapacityInUseInKb": 3145728,
+ "snapCapacityInUseOccupiedInKb": 0,
+ "spareCapacityInKb": 33239040,
+ "thickCapacityInUseInKb": 0,
+ "thinCapacityAllocatedInKb": 0,
+ "thinCapacityInUseInKb": 0,
+ "totalReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "totalWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "unreachableUnusedCapacityInKb": 0,
+ "unusedCapacityInKb": 299156480,
+ "userDataReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "userDataWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "volumeIds": [],
+ "vtreeIds": []
+ }
+ },
+ "System": {
+ "BackgroundScanCompareCount": 0,
+ "BackgroundScannedInMB": 0,
+ "activeBckRebuildCapacityInKb": 0,
+ "activeFwdRebuildCapacityInKb": 0,
+ "activeMovingCapacityInKb": 0,
+ "activeMovingInBckRebuildJobs": 0,
+ "activeMovingInFwdRebuildJobs": 0,
+ "activeMovingInNormRebuildJobs": 0,
+ "activeMovingInRebalanceJobs": 0,
+ "activeMovingOutBckRebuildJobs": 0,
+ "activeMovingOutFwdRebuildJobs": 0,
+ "activeMovingOutNormRebuildJobs": 0,
+ "activeMovingRebalanceJobs": 0,
+ "activeNormRebuildCapacityInKb": 0,
+ "activeRebalanceCapacityInKb": 0,
+ "atRestCapacityInKb": 50110464,
+ "bckRebuildCapacityInKb": 0,
+ "bckRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "bckRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "capacityAvailableForVolumeAllocationInKb": 243269632,
+ "capacityInUseInKb": 50110464,
+ "capacityLimitInKb": 643819520,
+ "degradedFailedCapacityInKb": 0,
+ "degradedFailedVacInKb": 0,
+ "degradedHealthyCapacityInKb": 0,
+ "degradedHealthyVacInKb": 0,
+ "failedCapacityInKb": 0,
+ "failedVacInKb": 0,
+ "fixedReadErrorCount": 0,
+ "fwdRebuildCapacityInKb": 0,
+ "fwdRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "fwdRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "inMaintenanceCapacityInKb": 0,
+ "inMaintenanceVacInKb": 0,
+ "inUseVacInKb": 67108864,
+ "maxCapacityInKb": 643819520,
+ "movingCapacityInKb": 0,
+ "normRebuildCapacityInKb": 0,
+ "normRebuildReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "normRebuildWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "numOfDevices": 6,
+ "numOfFaultSets": 0,
+ "numOfMappedToAllVolumes": 0,
+ "numOfProtectionDomains": 1,
+ "numOfRfcacheDevices": 0,
+ "numOfScsiInitiators": 0,
+ "numOfSdc": 3,
+ "numOfSds": 3,
+ "numOfSnapshots": 1,
+ "numOfStoragePools": 2,
+ "numOfThickBaseVolumes": 0,
+ "numOfThinBaseVolumes": 2,
+ "numOfUnmappedVolumes": 0,
+ "numOfVolumes": 3,
+ "numOfVolumesInDeletion": 0,
+ "numOfVtrees": 2,
+ "pendingBckRebuildCapacityInKb": 0,
+ "pendingFwdRebuildCapacityInKb": 0,
+ "pendingMovingCapacityInKb": 0,
+ "pendingMovingInBckRebuildJobs": 0,
+ "pendingMovingInFwdRebuildJobs": 0,
+ "pendingMovingInNormRebuildJobs": 0,
+ "pendingMovingInRebalanceJobs": 0,
+ "pendingMovingOutBckRebuildJobs": 0,
+ "pendingMovingOutFwdRebuildJobs": 0,
+ "pendingMovingOutNormrebuildJobs": 0,
+ "pendingMovingRebalanceJobs": 0,
+ "pendingNormRebuildCapacityInKb": 0,
+ "pendingRebalanceCapacityInKb": 0,
+ "primaryReadBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "primaryReadFromDevBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "primaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "primaryVacInKb": 33554432,
+ "primaryWriteBwc": {
+ "numOccured": 1556,
+ "numSeconds": 5,
+ "totalWeightInKb": 1193408
+ },
+ "protectedCapacityInKb": 50110464,
+ "protectedVacInKb": 67108864,
+ "protectionDomainIds": [
+ "74d855a900000000"
+ ],
+ "rebalanceCapacityInKb": 0,
+ "rebalancePerReceiveJobNetThrottlingInKbps": 0,
+ "rebalanceReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rebalanceWaitSendQLength": 0,
+ "rebalanceWriteBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "rebuildPerReceiveJobNetThrottlingInKbps": 0,
+ "rebuildWaitSendQLength": 0,
+ "rfacheReadHit": 0,
+ "rfacheWriteHit": 0,
+ "rfcacheAvgReadTime": 0,
+ "rfcacheAvgWriteTime": 0,
+ "rfcacheFdAvgReadTime": 0,
+ "rfcacheFdAvgWriteTime": 0,
+ "rfcacheFdCacheOverloaded": 0,
+ "rfcacheFdInlightReads": 0,
+ "rfcacheFdInlightWrites": 0,
+ "rfcacheFdIoErrors": 0,
+ "rfcacheFdMonitorErrorStuckIo": 0,
+ "rfcacheFdReadTimeGreater1Min": 0,
+ "rfcacheFdReadTimeGreater1Sec": 0,
+ "rfcacheFdReadTimeGreater500Millis": 0,
+ "rfcacheFdReadTimeGreater5Sec": 0,
+ "rfcacheFdReadsReceived": 0,
+ "rfcacheFdWriteTimeGreater1Min": 0,
+ "rfcacheFdWriteTimeGreater1Sec": 0,
+ "rfcacheFdWriteTimeGreater500Millis": 0,
+ "rfcacheFdWriteTimeGreater5Sec": 0,
+ "rfcacheFdWritesReceived": 0,
+ "rfcacheIoErrors": 0,
+ "rfcacheIosOutstanding": 0,
+ "rfcacheIosSkipped": 0,
+ "rfcachePooIosOutstanding": 0,
+ "rfcachePoolCachePages": 0,
+ "rfcachePoolEvictions": 0,
+ "rfcachePoolInLowMemoryCondition": 0,
+ "rfcachePoolIoTimeGreater1Min": 0,
+ "rfcachePoolLockTimeGreater1Sec": 0,
+ "rfcachePoolLowResourcesInitiatedPassthroughMode": 0,
+ "rfcachePoolNumCacheDevs": 0,
+ "rfcachePoolNumSrcDevs": 0,
+ "rfcachePoolPagesInuse": 0,
+ "rfcachePoolReadHit": 0,
+ "rfcachePoolReadMiss": 0,
+ "rfcachePoolReadPendingG10Millis": 0,
+ "rfcachePoolReadPendingG1Millis": 0,
+ "rfcachePoolReadPendingG1Sec": 0,
+ "rfcachePoolReadPendingG500Micro": 0,
+ "rfcachePoolReadsPending": 0,
+ "rfcachePoolSize": 0,
+ "rfcachePoolSourceIdMismatch": 0,
+ "rfcachePoolSuspendedIos": 0,
+ "rfcachePoolSuspendedPequestsRedundantSearchs": 0,
+ "rfcachePoolWriteHit": 0,
+ "rfcachePoolWriteMiss": 0,
+ "rfcachePoolWritePending": 0,
+ "rfcachePoolWritePendingG10Millis": 0,
+ "rfcachePoolWritePendingG1Millis": 0,
+ "rfcachePoolWritePendingG1Sec": 0,
+ "rfcachePoolWritePendingG500Micro": 0,
+ "rfcacheReadMiss": 0,
+ "rfcacheReadsFromCache": 0,
+ "rfcacheReadsPending": 0,
+ "rfcacheReadsReceived": 0,
+ "rfcacheReadsSkipped": 0,
+ "rfcacheReadsSkippedAlignedSizeTooLarge": 0,
+ "rfcacheReadsSkippedHeavyLoad": 0,
+ "rfcacheReadsSkippedInternalError": 0,
+ "rfcacheReadsSkippedLockIos": 0,
+ "rfcacheReadsSkippedLowResources": 0,
+ "rfcacheReadsSkippedMaxIoSize": 0,
+ "rfcacheReadsSkippedStuckIo": 0,
+ "rfcacheSkippedUnlinedWrite": 0,
+ "rfcacheSourceDeviceReads": 0,
+ "rfcacheSourceDeviceWrites": 0,
+ "rfcacheWriteMiss": 0,
+ "rfcacheWritePending": 0,
+ "rfcacheWritesReceived": 0,
+ "rfcacheWritesSkippedCacheMiss": 0,
+ "rfcacheWritesSkippedHeavyLoad": 0,
+ "rfcacheWritesSkippedInternalError": 0,
+ "rfcacheWritesSkippedLowResources": 0,
+ "rfcacheWritesSkippedMaxIoSize": 0,
+ "rfcacheWritesSkippedStuckIo": 0,
+ "rmPendingAllocatedInKb": 0,
+ "rmcache128kbEntryCount": 0,
+ "rmcache16kbEntryCount": 0,
+ "rmcache32kbEntryCount": 0,
+ "rmcache4kbEntryCount": 0,
+ "rmcache64kbEntryCount": 0,
+ "rmcache8kbEntryCount": 0,
+ "rmcacheBigBlockEvictionCount": 0,
+ "rmcacheBigBlockEvictionSizeCountInKb": 0,
+ "rmcacheCurrNumOf128kbEntries": 0,
+ "rmcacheCurrNumOf16kbEntries": 0,
+ "rmcacheCurrNumOf32kbEntries": 0,
+ "rmcacheCurrNumOf4kbEntries": 0,
+ "rmcacheCurrNumOf64kbEntries": 0,
+ "rmcacheCurrNumOf8kbEntries": 0,
+ "rmcacheEntryEvictionCount": 0,
+ "rmcacheEntryEvictionSizeCountInKb": 0,
+ "rmcacheNoEvictionCount": 0,
+ "rmcacheSizeInKb": 393216,
+ "rmcacheSizeInUseInKb": 0,
+ "rmcacheSkipCountCacheAllBusy": 0,
+ "rmcacheSkipCountLargeIo": 0,
+ "rmcacheSkipCountUnaligned4kbIo": 0,
+ "scsiInitiatorIds": [],
+ "sdcIds": [
+ "6076fd0f00000000",
+ "6076fd1000000001",
+ "6076fd1100000002"
+ ],
+ "secondaryReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromDevBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryReadFromRmcacheBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "secondaryVacInKb": 33554432,
+ "secondaryWriteBwc": {
+ "numOccured": 1530,
+ "numSeconds": 5,
+ "totalWeightInKb": 1169632
+ },
+ "semiProtectedCapacityInKb": 0,
+ "semiProtectedVacInKb": 0,
+ "snapCapacityInUseInKb": 19845120,
+ "snapCapacityInUseOccupiedInKb": 749568,
+ "spareCapacityInKb": 64380928,
+ "thickCapacityInUseInKb": 0,
+ "thinCapacityAllocatedInKb": 67108864,
+ "thinCapacityInUseInKb": 49360896,
+ "totalReadBwc": {
+ "numOccured": 1,
+ "numSeconds": 5,
+ "totalWeightInKb": 4
+ },
+ "totalWriteBwc": {
+ "numOccured": 3086,
+ "numSeconds": 5,
+ "totalWeightInKb": 2363040
+ },
+ "unreachableUnusedCapacityInKb": 0,
+ "unusedCapacityInKb": 529328128,
+ "userDataReadBwc": {
+ "numOccured": 0,
+ "numSeconds": 0,
+ "totalWeightInKb": 0
+ },
+ "userDataWriteBwc": {
+ "numOccured": 285,
+ "numSeconds": 1,
+ "totalWeightInKb": 227170
+ }
+ }
+} \ No newline at end of file