Skip to content

Commit

Permalink
feat: ONTAP Power calculation for embedded Shelf (#2333)
Browse files Browse the repository at this point in the history
* feat: ONTAP Power calculation for embedded Shelf
  • Loading branch information
rahulguptajss authored Aug 29, 2023
1 parent 09beef2 commit 4c81750
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 38 deletions.
24 changes: 24 additions & 0 deletions cmd/collectors/commonutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,30 @@ var validUnits = map[string]bool{
"W*hr": true,
}

type embedShelf struct {
model, moduleType string
}

// Reference https://kb.netapp.com/onprem/ontap/hardware/FAQ%3A_How_do_shelf_product_IDs_and_modules_in_ONTAP_map_to_a_model_of_a_shelf_or_storage_system_with_embedded_storage
// There are two ways to identify embedded disk shelves:
// 1. The shelf's module type ends with E
// 2. The shelf is listed in the link above
var combinations = map[embedShelf]bool{
embedShelf{"FS424-12", "IOM12F"}: true,
}

func IsEmbedShelf(model string, moduleType string) bool {
model = strings.ToUpper(model)
moduleType = strings.ToUpper(moduleType)

// if module type ends with E
if strings.HasSuffix(moduleType, "E") {
return true
}

return combinations[embedShelf{model, moduleType}]
}

func InvokeRestCall(client *rest.Client, href string, logger *logging.Logger) ([]gjson.Result, error) {
result, err := rest.Fetch(client, href)
if err != nil {
Expand Down
42 changes: 42 additions & 0 deletions cmd/collectors/rest/plugins/shelf/shelf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Package shelf Copyright NetApp Inc, 2021 All rights reserved
package shelf

import (
"github.com/netapp/harvest/v2/cmd/collectors"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
"github.com/netapp/harvest/v2/pkg/matrix"
)

type Shelf struct {
*plugin.AbstractPlugin
}

func New(p *plugin.AbstractPlugin) plugin.Plugin {
return &Shelf{AbstractPlugin: p}
}

func (my *Shelf) Init() error {
return my.InitAbc()
}

func (my *Shelf) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) {

data := dataMap[my.Object]
for _, instance := range data.GetInstances() {
if !instance.IsExportable() {
continue
}

model := instance.GetLabel("model")
moduleType := instance.GetLabel("module_type")

isEmbed := collectors.IsEmbedShelf(model, moduleType)
if isEmbed {
instance.SetLabel("isEmbedded", "Yes")
} else {
instance.SetLabel("isEmbedded", "No")
}
}
return nil, nil

}
3 changes: 3 additions & 0 deletions cmd/collectors/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/qtree"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/securityaccount"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/sensor"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/shelf"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/snapmirror"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/svm"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/volume"
Expand Down Expand Up @@ -403,6 +404,8 @@ func (r *Rest) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Plugin
return svm.New(abc)
case "Sensor":
return sensor.New(abc)
case "Shelf":
return shelf.New(abc)
case "SecurityAccount":
return securityaccount.New(abc)
case "QosPolicyFixed":
Expand Down
23 changes: 22 additions & 1 deletion cmd/collectors/zapi/plugins/shelf/shelf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package shelf

import (
"github.com/netapp/harvest/v2/cmd/collectors"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
"github.com/netapp/harvest/v2/pkg/api/ontapi/zapi"
"github.com/netapp/harvest/v2/pkg/conf"
Expand Down Expand Up @@ -55,6 +56,10 @@ func (my *Shelf) Init() error {
return err
}

if my.client.IsClustered() {
return nil
}

my.query = "storage-shelf-environment-list-info"

my.Logger.Debug().Msg("plugin connected!")
Expand Down Expand Up @@ -130,6 +135,7 @@ func (my *Shelf) Init() error {

// setup batchSize for request
my.batchSize = BatchSize

return nil
}

Expand All @@ -141,11 +147,26 @@ func (my *Shelf) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error
)

data := dataMap[my.Object]
// Only 7mode is supported through this plugin
if my.client.IsClustered() {
for _, instance := range data.GetInstances() {
if !instance.IsExportable() {
continue
}

model := instance.GetLabel("model")
moduleType := instance.GetLabel("module_type")

isEmbed := collectors.IsEmbedShelf(model, moduleType)
if isEmbed {
instance.SetLabel("isEmbedded", "Yes")
} else {
instance.SetLabel("isEmbedded", "No")
}
}
return nil, nil
}

// 7 mode handling
for _, instance := range data.GetInstances() {
if !instance.IsExportable() {
continue
Expand Down
2 changes: 2 additions & 0 deletions conf/rest/9.12.0/shelf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ endpoints:


plugins:
- Shelf
- LabelAgent:
replace:
- state state `ok` `online`
Expand All @@ -30,6 +31,7 @@ export_options:
instance_keys:
- shelf
instance_labels:
- isEmbedded
- model
- module_type
- op_status
Expand Down
26 changes: 14 additions & 12 deletions conf/zapi/cdot/9.8.0/shelf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,27 @@ object: shelf
counters:
storage-shelf-info:
- ^^shelf-uid
- ^module-type
- ^op-status
- ^serial-number
- ^shelf => shelf
- ^shelf-model
- ^state
- ^vendor-name
- disk-count
- ^module-type => module_type
- ^op-status => op_status
- ^serial-number => serial_number
- ^shelf => shelf
- ^shelf-model => model
- ^state => state
- ^vendor-name => vendor_name
- disk-count => disk_count

plugins:
LabelAgent:
# metric label zapi_value rest_value `default_value`
value_to_num:
- new_status state online ok `0`
- Shelf
- LabelAgent:
# metric label zapi_value rest_value `default_value`
value_to_num:
- new_status state online ok `0`

export_options:
instance_keys:
- shelf
instance_labels:
- isEmbedded
- model
- module_type
- op_status
Expand Down
53 changes: 28 additions & 25 deletions grafana/dashboards/cmode/power.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"gnetId": null,
"graphTooltip": 1,
"id": null,
"iteration": 1689849302689,
"iteration": 1693298975439,
"links": [
{
"asDropdown": true,
Expand Down Expand Up @@ -113,7 +113,7 @@
},
"id": 101,
"options": {
"content": "If an ONTAP system has **embedded** shelves, you may not see power and temperature information for those shelves since power and temperature are calculated at the cluster level.",
"content": "In an ONTAP system with **embedded** disk shelves, power and temperature data might not be visible for individual shelves. This is because these metrics are computed at the cluster level, not at the level of individual shelves.\n\nEmbedded shelf power is shared among the common nodes.",
"mode": "markdown"
},
"pluginVersion": "8.1.8",
Expand Down Expand Up @@ -183,7 +183,7 @@
"targets": [
{
"exemplar": false,
"expr": "(sum(environment_sensor_power{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"}) or vector(0)) + (sum(shelf_power{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"}) or vector(0))",
"expr": "(sum(environment_sensor_power{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"}) or vector(0)) + (sum(shelf_power{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} * on(datacenter,cluster,shelf) shelf_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",isEmbedded=\"No\"}) or vector(0))",
"format": "time_series",
"hide": false,
"instant": false,
Expand All @@ -195,7 +195,7 @@
],
"timeFrom": null,
"timeShift": null,
"title": "Cluster Power (Node + Shelf)",
"title": "Total Power",
"type": "stat"
},
{
Expand Down Expand Up @@ -2849,7 +2849,7 @@
"h": 7,
"w": 24,
"x": 0,
"y": 54
"y": 58
},
"id": 81,
"interval": "1m",
Expand Down Expand Up @@ -2988,6 +2988,7 @@
"options": {
"include": {
"names": [
"cluster",
"datacenter",
"model",
"module_type",
Expand All @@ -3004,11 +3005,11 @@
"Value #K",
"Value #F",
"Value #G",
"Value #L",
"Value #H",
"Value #I",
"Value #J",
"Value #L",
"cluster"
"isEmbedded"
]
}
}
Expand All @@ -3026,27 +3027,28 @@
"state": true
},
"indexByName": {
"Value #A": 19,
"Value #B": 16,
"Value #C": 20,
"Value #D": 4,
"Value #E": 5,
"Value #F": 7,
"Value #G": 8,
"Value #H": 10,
"Value #I": 11,
"Value #J": 12,
"Value #K": 6,
"Value #L": 9,
"Value #A": 20,
"Value #B": 17,
"Value #C": 21,
"Value #D": 5,
"Value #E": 6,
"Value #F": 8,
"Value #G": 9,
"Value #H": 11,
"Value #I": 12,
"Value #J": 13,
"Value #K": 7,
"Value #L": 10,
"cluster": 1,
"datacenter": 0,
"isEmbedded": 4,
"model": 3,
"module_type": 15,
"op_status": 17,
"serial_number": 13,
"module_type": 16,
"op_status": 18,
"serial_number": 14,
"shelf": 2,
"state": 18,
"vendor_name": 14
"state": 19,
"vendor_name": 15
},
"renameByName": {
"Value #A": "",
Expand All @@ -3061,6 +3063,7 @@
"Value #J": "Min Fan Speed (rpm)",
"Value #K": "Min Ambient Temp (C)",
"Value #L": "Min Temp (C)",
"isEmbedded": "Is Embedded",
"module_type": "",
"op_status": "",
"shelf_id": ""
Expand Down Expand Up @@ -3396,5 +3399,5 @@
"timezone": "",
"title": "ONTAP: Power",
"uid": "",
"version": 9
"version": 10
}

0 comments on commit 4c81750

Please sign in to comment.