Skip to content

Commit

Permalink
feat: data protection dashboard - part1 - snapshots (#664)
Browse files Browse the repository at this point in the history
* feat: data protection dashboard - part1 - snapshots
  • Loading branch information
Hardikl authored Dec 2, 2021
1 parent 19cd932 commit 8b9b93f
Show file tree
Hide file tree
Showing 5 changed files with 1,802 additions and 1 deletion.
3 changes: 3 additions & 0 deletions cmd/collectors/zapi/collector/zapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"goharvest2/cmd/collectors/zapi/plugins/quota"
"goharvest2/cmd/collectors/zapi/plugins/shelf"
"goharvest2/cmd/collectors/zapi/plugins/snapmirror"
"goharvest2/cmd/collectors/zapi/plugins/snapshot"
"goharvest2/cmd/collectors/zapiperf/plugins/fcp"
"goharvest2/cmd/collectors/zapiperf/plugins/headroom"
"goharvest2/cmd/collectors/zapiperf/plugins/nic"
Expand Down Expand Up @@ -145,6 +146,8 @@ func (me *Zapi) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Plugi
return volume.New(abc)
case "Qtree":
return quota.New(abc)
case "Snapshot":
return snapshot.New(abc)
default:
me.Logger.Info().Msgf("no zapi plugin found for %s", kind)
}
Expand Down
199 changes: 199 additions & 0 deletions cmd/collectors/zapi/plugins/snapshot/snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package snapshot

import (
"goharvest2/cmd/poller/collector"
"goharvest2/cmd/poller/plugin"
"goharvest2/pkg/api/ontapi/zapi"
"goharvest2/pkg/conf"
"goharvest2/pkg/dict"
"goharvest2/pkg/errors"
"goharvest2/pkg/matrix"
"goharvest2/pkg/tree/node"
"strconv"
"strings"
)

const BatchSize = "500"

type Snapshot struct {
*plugin.AbstractPlugin
data *matrix.Matrix
instanceKeys map[string]string
instanceLabels map[string]*dict.Dict
batchSize string
client *zapi.Client
query string
}

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

func (my *Snapshot) Init() error {

var err error

if err = my.InitAbc(); err != nil {
return err
}

if my.client, err = zapi.New(conf.ZapiPoller(my.ParentParams)); err != nil {
my.Logger.Error().Stack().Err(err).Msg("connecting")
return err
}

if err = my.client.Init(5); err != nil {
return err
}

my.query = "snapshot-policy-get-iter"
my.Logger.Debug().Msg("plugin connected!")

my.data = matrix.New(my.Parent+".Snapshot", "snapshot", "snapshot")
my.instanceKeys = make(map[string]string)
my.instanceLabels = make(map[string]*dict.Dict)

exportOptions := node.NewS("export_options")
instanceKeys := exportOptions.NewChildS("instance_keys", "")

instanceKeys.NewChildS("", "vserver")
instanceKeys.NewChildS("", "snapshot_policy")
instanceKeys.NewChildS("", "comment")

objects := my.Params.GetChildS("objects")
if objects == nil {
return errors.New(errors.MISSING_PARAM, "objects")
}

for _, obj := range objects.GetAllChildContentS() {
metricName, display := collector.ParseMetricName(obj)

metric, err := my.data.NewMetricFloat64(metricName)
if err != nil {
my.Logger.Error().Stack().Err(err).Msg("add metric")
return err
}

metric.SetName(display)
my.Logger.Debug().Msgf("added metric: (%s) [%s] %s", metricName, display, metric)
}

my.Logger.Debug().Msgf("added data with %d metrics", len(my.data.GetMetrics()))
my.data.SetExportOptions(exportOptions)

// batching the request
if my.client.IsClustered() {
if b := my.Params.GetChildContentS("batch_size"); b != "" {
if _, err := strconv.Atoi(b); err == nil {
my.batchSize = b
my.Logger.Info().Msgf("using batch-size [%s]", my.batchSize)
}
} else {
my.batchSize = BatchSize
my.Logger.Trace().Str("BatchSize", BatchSize).Msg("Using default batch-size")
}
}

return nil
}

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

var (
request, result *node.Node
policyInfos []*node.Node
tag string
err error
)

var output []*matrix.Matrix

// Purge and reset data
my.data.PurgeInstances()
my.data.Reset()

// Set all global labels from zapi.go if already not exist
my.data.SetGlobalLabels(data.GetGlobalLabels())

request = node.NewXmlS(my.query)
if my.client.IsClustered() && my.batchSize != "" {
request.NewChildS("max-records", my.batchSize)
}

tag = "initial"

for {
result, tag, err = my.client.InvokeBatchRequest(request, tag)

if err != nil {
return nil, err
}

if result == nil {
break
}

if x := result.GetChildS("attributes-list"); x != nil {
policyInfos = x.GetChildren()
}

if len(policyInfos) == 0 {
return nil, errors.New(errors.ERR_NO_INSTANCE, "no snapshot policy info instances found")
}

my.Logger.Debug().Msgf("fetching %d snapshot policy counters", len(policyInfos))

for policyInfoIndex, policyInfo := range policyInfos {

var comment string
vserver := policyInfo.GetChildContentS("vserver-name")
policyName := policyInfo.GetChildContentS("policy")
if comment = policyInfo.GetChildContentS("comment"); comment == "" {
comment = "No Comment"
}

for attribute, m := range my.data.GetMetrics() {

objectElem := policyInfo.GetChildS(attribute)
if objectElem == nil {
my.Logger.Warn().Msgf("no [%s] instances on this %s.%s.%s", attribute, vserver, policyName, comment)
continue
}

if attrValue := policyInfo.GetChildContentS(attribute); attrValue != "" {
// Ex. InstanceKey: fas8040-206-21.default.Default policy with hourly, daily.12.total-schedules
instanceKey := vserver + "." + policyName + "." + comment + "." + strconv.Itoa(policyInfoIndex) + "." + attribute
//my.Logger.Info().Msgf(instanceKey)
instance, err := my.data.NewInstance(instanceKey)

if err != nil {
my.Logger.Debug().Msgf("add (%s) instance: %v", attribute, err)
return nil, err
}

my.Logger.Debug().Msgf("add (%s) instance: %s.%s.%s", attribute, vserver, policyName, comment)

instance.SetLabel("vserver", vserver)
instance.SetLabel("snapshot_policy", policyName)
instance.SetLabel("comment", comment)

// populate numeric data
if value := strings.Split(attrValue, " ")[0]; value != "" {
if err := m.SetValueString(instance, value); err != nil {
my.Logger.Debug().Msgf("(%s) failed to parse value (%s): %v", attribute, value, err)
} else {
my.Logger.Debug().Msgf("(%s) added value (%s)", attribute, value)
}
}

} else {
my.Logger.Debug().Msgf("instance without [%s], skipping", attribute)
}

output = append(output, my.data)
}
}

}
return output, nil
}
9 changes: 9 additions & 0 deletions conf/zapi/cdot/9.8.0/volume.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@ counters:
- ^state
- ^status

- volume-snapshot-attributes:
- ^auto-snapshots-enabled => auto_snapshots_enabled
- ^snapshot-policy
- snapshot-count

plugins:
Snapshot:
objects:
- total-schedules
LabelAgent:
# metric label zapi_value rest_value `default_value`
value_to_num:
Expand All @@ -80,4 +88,5 @@ export_options:
instance_labels:
- state
- is_sis_volume
- snapshot_policy

Loading

0 comments on commit 8b9b93f

Please sign in to comment.