Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
540 changes: 540 additions & 0 deletions cmd/collectors/cmperf/cmperf.go

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/disk/disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package disk

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/disk"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf Disk plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return disk.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/fabricpool/fabricpool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fabricpool

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/fabricpool"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf fabricpool plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return fabricpool.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/fcp/fcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fcp

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/fcp"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf FCP plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return fcp.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/fcvi/fcvi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fcvi

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/fcvi"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf FCVI plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return fcvi.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/flexcache/flexcache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package flexcache

import (
"github.com/netapp/harvest/v2/cmd/collectors/statperf/plugins/flexcache"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This uses the statperf flexcache plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return flexcache.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/headroom/headroom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package headroom

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/headroom"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf Headroom plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return headroom.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/nic/nic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nic

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/nic"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf NIC plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return nic.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/volume/volume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package volume

import (
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/volume"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This reuses the restperf volume plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return volume.New(p)
}
11 changes: 11 additions & 0 deletions cmd/collectors/cmperf/plugins/vscan/vscan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package vscan

import (
"github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/vscan"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
)

// New This uses the zapiperf vscan plugin implementation as the functionality is identical
func New(p *plugin.AbstractPlugin) plugin.Plugin {
return vscan.New(p)
}
2 changes: 1 addition & 1 deletion cmd/collectors/zapiperf/zapiperf.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func (z *ZapiPerf) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Pl
case "FlexCache":
return flexcache.New(abc)
default:
z.Logger.Info("no zapiPerf plugin found for %s", slog.String("kind", kind))
z.Logger.Info("no zapiPerf plugin found", slog.String("kind", kind))
}
return nil
}
Expand Down
100 changes: 96 additions & 4 deletions cmd/poller/poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package main

import (
"bytes"
"cmp"
"context"
"crypto/fips140"
"crypto/tls"
Expand Down Expand Up @@ -55,6 +56,7 @@ import (
"github.com/goccy/go-yaml/parser"
"github.com/netapp/harvest/v2/cmd/collectors"
_ "github.com/netapp/harvest/v2/cmd/collectors/cisco"
_ "github.com/netapp/harvest/v2/cmd/collectors/cmperf"
_ "github.com/netapp/harvest/v2/cmd/collectors/ems"
_ "github.com/netapp/harvest/v2/cmd/collectors/eseries"
_ "github.com/netapp/harvest/v2/cmd/collectors/eseriesperf"
Expand Down Expand Up @@ -82,6 +84,7 @@ import (
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/requests"
"github.com/netapp/harvest/v2/pkg/slogx"
harvestTemplate "github.com/netapp/harvest/v2/pkg/template"
"github.com/netapp/harvest/v2/pkg/tree/node"
version2 "github.com/netapp/harvest/v2/pkg/version"
goversion "github.com/netapp/harvest/v2/third_party/go-version"
Expand Down Expand Up @@ -905,6 +908,11 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error {
}
}

// Build CmPerf manifest from the already-initialized CmPerf collectors.
if manifest := buildCmPerfManifest(cols, p.getCmManifestName()); manifest != nil {
deleteAndPostCmManifest(manifest)
}
Comment thread
cgrinds marked this conversation as resolved.

p.collectors = append(p.collectors, cols...)
// link each collector with requested exporter & update metadata
for _, col := range cols {
Expand Down Expand Up @@ -942,6 +950,85 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error {
return nil
}

// cmPerfPresetDetail holds the per-object section of a CmPerf manifest.
type cmPerfPresetDetail struct {
Object string `json:"object"`
SamplePeriod string `json:"sample-period"`
Counters []string `json:"counters"`
}

// cmPerfManifestJSON is the top-level CmPerf manifest structure.
type cmPerfManifestJSON struct {
Preset string `json:"preset"`
PresetDetails []cmPerfPresetDetail `json:"preset_details"`
}

func deleteAndPostCmManifest(_ []byte) {
// TODO implement
}

// buildCmPerfManifest constructs a JSON manifest from the already-initialized CmPerf
// collectors. It reads query, counters, and schedule from the collector's merged params
// (i.e. default.yaml + per-object sub-template).
Comment thread
cgrinds marked this conversation as resolved.
// preset_details are sorted by object; counters within each entry are sorted.
func buildCmPerfManifest(cols []collector.Collector, manifestName string) []byte {
const defaultDataPeriod = "1m"

var details []cmPerfPresetDetail
for _, col := range cols {
if col.GetName() != "CmPerf" {
continue
}
params := col.GetParams()

query := params.GetChildContentS("query")
if query == "" {
continue
}

// At the moment, only the defaultDataPeriod is supported by ONTAP
dataPeriod := defaultDataPeriod

var counters []string
if countersNode := params.GetChildS("counters"); countersNode != nil {
for _, raw := range countersNode.GetAllChildContentS() {
if raw == "" {
continue
}
name, _, _, _ := harvestTemplate.ParseMetric(raw)
counters = append(counters, name)
}
}
slices.Sort(counters)

details = append(details, cmPerfPresetDetail{
Object: query,
SamplePeriod: dataPeriod,
Counters: counters,
})
}

if len(details) == 0 {
return nil
}

slices.SortFunc(details, func(a, b cmPerfPresetDetail) int {
return strings.Compare(a.Object, b.Object)
})

manifest := cmPerfManifestJSON{
Preset: manifestName,
PresetDetails: details,
}
data, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
logger.Error("buildCmPerfManifest: failed to marshal manifest", slogx.Err(err))
return nil
}
logger.Info("built CmPerf manifest", slog.Int("objects", len(details)))
return data
}

func nonOverlappingCollectors(objectCollectors []objectCollector) []objectCollector {
if len(objectCollectors) == 0 {
return []objectCollector{}
Expand All @@ -953,11 +1040,12 @@ func nonOverlappingCollectors(objectCollectors []objectCollector) []objectCollec
unique := make([]objectCollector, 0)
conflicts := map[string][]string{
"Zapi": {"Rest"},
"ZapiPerf": {"RestPerf", "KeyPerf", "StatPerf"},
"ZapiPerf": {"RestPerf", "KeyPerf", "StatPerf", "CmPerf"},
"Rest": {"Zapi"},
"RestPerf": {"ZapiPerf", "KeyPerf", "StatPerf"},
"KeyPerf": {"ZapiPerf", "RestPerf", "StatPerf"},
"StatPerf": {"ZapiPerf", "RestPerf", "KeyPerf"},
"RestPerf": {"ZapiPerf", "KeyPerf", "StatPerf", "CmPerf"},
"KeyPerf": {"ZapiPerf", "RestPerf", "StatPerf", "CmPerf"},
"StatPerf": {"ZapiPerf", "RestPerf", "KeyPerf", "CmPerf"},
"CmPerf": {"ZapiPerf", "RestPerf", "KeyPerf", "StatPerf"},
}

// Sort collectors so native ones (viaRedirection=false) come before redirected ones
Expand Down Expand Up @@ -1894,6 +1982,10 @@ func (p *Poller) truncateReason(msg string) string {
return strings.ReplaceAll(msg, "\"", "")
}

func (p *Poller) getCmManifestName() string {
return cmp.Or(p.params.CmPerfManifest, p.name)
}

func startPoller(_ *cobra.Command, _ []string) {
poller := &Poller{}
poller.options = opts
Expand Down
Loading
Loading