Skip to content

Commit

Permalink
fix: handle batching in shelf plugin (#1429)
Browse files Browse the repository at this point in the history
* fix: handle batching in shelf plugin

* fix: handle batching at common place

* fix: removed unused var

* fix: few zapi calls dont support max-records param

* fix: handled shelf changes in closure way

* feat: handle ZAPI batching with closure (#1444)

* feat: handle ZAPI batching with closure

* feat: handle ZAPI batching with closure

* feat: handle ZAPI batching with closure
feat: Add LogSet support to plugins

* fix: 7mode record check

* fix: review comment

* fix: log change

Co-authored-by: Chris Grindstaff <[email protected]>
  • Loading branch information
Hardikl and cgrinds authored Nov 14, 2022
1 parent 75f8dbd commit 44549cd
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 109 deletions.
44 changes: 3 additions & 41 deletions cmd/collectors/commonutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package collectors

import (
"github.com/netapp/harvest/v2/cmd/tools/rest"
"github.com/netapp/harvest/v2/pkg/api/ontapi/zapi"
"github.com/netapp/harvest/v2/pkg/logging"
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/tree/node"
Expand All @@ -11,6 +10,8 @@ import (
"time"
)

const DefaultBatchSize = "500"

func InvokeRestCall(client *rest.Client, href string, logger *logging.Logger) ([]gjson.Result, error) {
result, err := rest.Fetch(client, href)
if err != nil {
Expand All @@ -25,45 +26,6 @@ func InvokeRestCall(client *rest.Client, href string, logger *logging.Logger) ([
return result, nil
}

func InvokeZapiCall(client *zapi.Client, request *node.Node, logger *logging.Logger, tag string) ([]*node.Node, string, error) {

var (
result *node.Node
response []*node.Node
newTag string
err error
)

if tag != "" {
if result, newTag, err = client.InvokeBatchRequest(request, tag); err != nil {
return nil, "", err
}
} else {
if result, err = client.InvokeRequest(request); err != nil {
return nil, "", err
}
}

if result == nil {
return nil, "", nil
}

if x := result.GetChildS("attributes-list"); x != nil {
response = x.GetChildren()
} else if y := result.GetChildS("attributes"); y != nil {
// Check for non-list response
response = y.GetChildren()
}

if len(response) == 0 {
return nil, "", nil
}

logger.Trace().Int("object", len(response)).Msg("fetching")

return response, newTag, nil
}

func UpdateProtectedFields(instance *matrix.Instance) {

// check for group_type
Expand Down Expand Up @@ -161,7 +123,7 @@ func GetDataInterval(param *node.Node, defaultInterval time.Duration) float64 {
return defaultInterval.Seconds()
}

// timestamp in micro seconds
// IsTimestampOlderThanDuration - timestamp units are micro seconds
func IsTimestampOlderThanDuration(timestamp float64, duration time.Duration) bool {
return time.Since(time.UnixMicro(int64(timestamp))) > duration
}
11 changes: 7 additions & 4 deletions cmd/collectors/zapi/plugins/certificate/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ func (my *Certificate) Init() error {
return err
}

my.batchSize = BatchSize
if b := my.Params.GetChildContentS("batch_size"); b != "" {
if _, err := strconv.Atoi(b); err == nil {
my.batchSize = b
}
} else {
my.batchSize = BatchSize
}

return nil
Expand Down Expand Up @@ -204,7 +203,8 @@ func (my *Certificate) GetAdminVserver() (string, error) {
vserverInfo := query.NewChildS("vserver-info", "")
vserverInfo.NewChildS("vserver-type", "admin")

if result, _, err = collectors.InvokeZapiCall(my.client, request, my.Logger, ""); err != nil {
// Fetching only admin SVMs
if result, err = my.client.InvokeZapiCall(request); err != nil {
return "", err
}

Expand All @@ -214,6 +214,7 @@ func (my *Certificate) GetAdminVserver() (string, error) {
// This should be one iteration only as cluster can have one admin vserver
for _, svm := range result {
adminVserver = svm.GetChildContentS("vserver-name")
break
}
return adminVserver, nil
}
Expand All @@ -233,7 +234,8 @@ func (my *Certificate) GetSecuritySsl(adminSvm string) (string, error) {
vserverInfo := query.NewChildS("vserver-ssl-info", "")
vserverInfo.NewChildS("vserver", adminSvm)

if result, _, err = collectors.InvokeZapiCall(my.client, request, my.Logger, ""); err != nil {
// fetching data of only admin vservers
if result, err = my.client.InvokeZapiCall(request); err != nil {
return "", err
}

Expand All @@ -243,6 +245,7 @@ func (my *Certificate) GetSecuritySsl(adminSvm string) (string, error) {
// This should be one iteration only as cluster can have one admin vserver
for _, ssl := range result {
certificateSerial = ssl.GetChildContentS("certificate-serial-number")
break
}
return certificateSerial, nil
}
3 changes: 1 addition & 2 deletions cmd/collectors/zapi/plugins/qtree/qtree.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,12 @@ func (my *Qtree) Init() error {
my.Logger.Debug().Msgf("added data with %d metrics", len(my.data.GetMetrics()))

// setup batchSize for request
my.batchSize = BatchSize
if my.client.IsClustered() {
if b := my.Params.GetChildContentS("batch_size"); b != "" {
if _, err := strconv.Atoi(b); err == nil {
my.batchSize = b
}
} else {
my.batchSize = BatchSize
}
}

Expand Down
8 changes: 6 additions & 2 deletions cmd/collectors/zapi/plugins/security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ func (my *Security) getSecurityConfig() (string, error) {
request = node.NewXMLS("security-config-get")
request.NewChildS("interface", "ssl")

if result, _, err = collectors.InvokeZapiCall(my.client, request, my.Logger, ""); err != nil {
// fetching only ssl interface
if result, err = my.client.InvokeZapiCall(request); err != nil {
return "", err
}

Expand All @@ -116,6 +117,7 @@ func (my *Security) getSecurityConfig() (string, error) {

for _, securityConfig := range result {
fipsEnabled = securityConfig.GetChildContentS("is-fips-enabled")
break
}
return fipsEnabled, nil
}
Expand Down Expand Up @@ -153,7 +155,8 @@ func (my *Security) getEnabledValue(request *node.Node) (string, error) {
err error
)

if result, _, err = collectors.InvokeZapiCall(my.client, request, my.Logger, ""); err != nil {
// fetching only telnet/rsh protocols
if result, err = my.client.InvokeZapiCall(request); err != nil {
return "", err
}

Expand All @@ -163,6 +166,7 @@ func (my *Security) getEnabledValue(request *node.Node) (string, error) {

for _, securityConfig := range result {
enabled = securityConfig.GetChildContentS("enabled")
break
}

return enabled, nil
Expand Down
78 changes: 46 additions & 32 deletions cmd/collectors/zapi/plugins/shelf/shelf.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import (
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/tree/node"
"github.com/netapp/harvest/v2/pkg/util"
"strconv"
"strings"
)

const BatchSize = "500"

type Shelf struct {
*plugin.AbstractPlugin
data map[string]*matrix.Matrix
instanceKeys map[string]string
instanceLabels map[string]*dict.Dict
batchSize string
client *zapi.Client
query string
}
Expand Down Expand Up @@ -139,14 +143,24 @@ func (my *Shelf) Init() error {
}

my.Logger.Debug().Msgf("initialized with data [%d] objects", len(my.data))

// setup batchSize for request
my.batchSize = BatchSize
if my.client.IsClustered() {
if b := my.Params.GetChildContentS("batch_size"); b != "" {
if _, err := strconv.Atoi(b); err == nil {
my.batchSize = b
}
}
}
return nil
}

func (my *Shelf) Run(data *matrix.Matrix) ([]*matrix.Matrix, error) {

var (
result *node.Node
err error
output []*matrix.Matrix
)

if !my.client.IsClustered() {
Expand All @@ -155,16 +169,18 @@ func (my *Shelf) Run(data *matrix.Matrix) ([]*matrix.Matrix, error) {
}
}

if result, err = my.client.InvokeRequestString(my.query); err != nil {
return nil, err
}

// Set all global labels from zapi.go if already not exist
for a := range my.instanceLabels {
my.data[a].SetGlobalLabels(data.GetGlobalLabels())
}

var output []*matrix.Matrix
request := node.NewXMLS(my.query)
request.NewChildS("max-records", my.batchSize)

result, err := my.client.InvokeZapiCall(request)
if err != nil {
return nil, err
}

if my.client.IsClustered() {
output, err = my.handleCMode(result)
Expand All @@ -176,14 +192,15 @@ func (my *Shelf) Run(data *matrix.Matrix) ([]*matrix.Matrix, error) {
}

if my.client.IsClustered() {
return my.calculateEnvironmentMetrics(output, data)
} else {
return output, nil
err := my.calculateEnvironmentMetrics(data)
if err != nil {
return nil, err
}
}

return output, nil
}

func (my *Shelf) calculateEnvironmentMetrics(output []*matrix.Matrix, data *matrix.Matrix) ([]*matrix.Matrix, error) {
func (my *Shelf) calculateEnvironmentMetrics(data *matrix.Matrix) error {
var err error
shelfEnvironmentMetricMap := make(map[string]*shelfEnvironmentMetric, 0)
for _, o := range my.data {
Expand Down Expand Up @@ -326,25 +343,16 @@ func (my *Shelf) calculateEnvironmentMetrics(output []*matrix.Matrix, data *matr
}
}
}
return output, nil
return nil
}

func (my *Shelf) handleCMode(result *node.Node) ([]*matrix.Matrix, error) {
func (my *Shelf) handleCMode(shelves []*node.Node) ([]*matrix.Matrix, error) {
var (
shelves []*node.Node
output []*matrix.Matrix
)

if x := result.GetChildS("attributes-list"); x != nil {
shelves = x.GetChildren()
}
if len(shelves) == 0 {
return nil, errs.New(errs.ErrNoInstance, "no shelf instances found")
}

my.Logger.Debug().Msgf("fetching %d shelf counters", len(shelves))

var output []*matrix.Matrix

// Purge and reset data
for _, data1 := range my.data {
data1.PurgeInstances()
Expand Down Expand Up @@ -399,7 +407,7 @@ func (my *Shelf) handleCMode(result *node.Node) ([]*matrix.Matrix, error) {
instance.SetLabel("shelf", shelfName)
instance.SetLabel("shelf_id", shelfID)

// Each child would have different possible values which is ugly way to write all of them,
// Each child would have different possible values which is an ugly way to write all of them,
// so normal value would be mapped to 1 and rest all are mapped to 0.
if instance.GetLabel("status") == "normal" {
_ = statusMetric.SetValueInt64(instance, 1)
Expand Down Expand Up @@ -431,19 +439,25 @@ func (my *Shelf) handleCMode(result *node.Node) ([]*matrix.Matrix, error) {
return output, nil
}

func (my *Shelf) handle7Mode(result *node.Node) ([]*matrix.Matrix, error) {
func (my *Shelf) handle7Mode(result []*node.Node) ([]*matrix.Matrix, error) {
var (
shelves []*node.Node
channels []*node.Node
output []*matrix.Matrix
)
//fallback to 7mode
channels = result.SearchChildren([]string{"shelf-environ-channel-info"})

if len(channels) == 0 {
return nil, errs.New(errs.ErrNoInstance, "no channels found")
// Result would be the zapi response itself with only one record.
if len(result) != 1 {
my.Logger.Debug().Msg("no shelves found")
return output, nil
}
// fallback to 7mode
channels = result[0].SearchChildren([]string{"shelf-environ-channel-info"})

var output []*matrix.Matrix
if len(channels) == 0 {
my.Logger.Debug().Msg("no channels found")
return output, nil
}

// Purge and reset data
for _, data1 := range my.data {
Expand All @@ -456,7 +470,7 @@ func (my *Shelf) handle7Mode(result *node.Node) ([]*matrix.Matrix, error) {
shelves = channel.SearchChildren([]string{"shelf-environ-shelf-list", "shelf-environ-shelf-info"})

if len(shelves) == 0 {
my.Logger.Warn().Str("channel", channelName).Msg("no shelves found")
my.Logger.Debug().Str("channel", channelName).Msg("no shelves found")
continue
}

Expand Down Expand Up @@ -504,7 +518,7 @@ func (my *Shelf) handle7Mode(result *node.Node) ([]*matrix.Matrix, error) {
instance.SetLabel("shelf_id", shelfID)
instance.SetLabel("channel", channelName)

// Each child would have different possible values which is ugly way to write all of them,
// Each child would have different possible values which is an ugly way to write all of them,
// so normal value would be mapped to 1 and rest all are mapped to 0.
if instance.GetLabel("status") == "normal" {
_ = statusMetric.SetValueInt64(instance, 1)
Expand Down
6 changes: 4 additions & 2 deletions cmd/collectors/zapi/plugins/snapmirror/snapmirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (my *SnapMirror) Run(data *matrix.Matrix) ([]*matrix.Matrix, error) {
}

for _, instance := range data.GetInstances() {
// Zapi call with `expand=true` would gives all the constituent's relationships as well, which we don't want to export.
// Zapi call with `expand=true` returns all the constituent's relationships. We do not want to export them.
if match := flexgroupConstituentName.FindStringSubmatch(instance.GetLabel("destination_volume")); len(match) == 3 {
instance.SetExportable(false)
continue
Expand Down Expand Up @@ -185,6 +185,7 @@ func (my *SnapMirror) getSVMPeerData(cluster string) error {
)

request := node.NewXMLS("vserver-peer-get-iter")
request.NewChildS("max-records", collectors.DefaultBatchSize)
// Fetching only remote vserver-peer
query := request.NewChildS("query", "")
vserverPeerInfo := query.NewChildS("vserver-peer-info", "")
Expand All @@ -193,7 +194,8 @@ func (my *SnapMirror) getSVMPeerData(cluster string) error {
// Clean svmPeerMap map
my.svmPeerDataMap = make(map[string]Peer)

if result, _, err = collectors.InvokeZapiCall(my.client, request, my.Logger, ""); err != nil {
// fetching only remote vserver peer data
if result, err = my.client.InvokeZapiCall(request); err != nil {
return err
}

Expand Down
Loading

0 comments on commit 44549cd

Please sign in to comment.