diff --git a/cmd/collectors/ems/ems_test.go b/cmd/collectors/ems/ems_test.go index 10fb84a2b..d3e9c2db7 100644 --- a/cmd/collectors/ems/ems_test.go +++ b/cmd/collectors/ems/ems_test.go @@ -54,7 +54,7 @@ func NewEms() *Ems { opts.HomePath = homePath opts.IsTest = true - ac := collector.New("Ems", "Ems", opts, emsParams(emsConfigPath), nil) + ac := collector.New("Ems", "Ems", opts, emsParams(emsConfigPath), nil, conf.Remote{}) e := &Ems{} if err := e.Init(ac); err != nil { slog.Error("", slogx.Err(err)) diff --git a/cmd/collectors/keyperf/keyperf.go b/cmd/collectors/keyperf/keyperf.go index bd3516e2d..9c7018410 100644 --- a/cmd/collectors/keyperf/keyperf.go +++ b/cmd/collectors/keyperf/keyperf.go @@ -68,8 +68,6 @@ func (kp *KeyPerf) Init(a *collector.AbstractCollector) error { return err } - kp.Remote = kp.Client.Remote() - if kp.Prop.TemplatePath, err = kp.LoadTemplate(); err != nil { return err } diff --git a/cmd/collectors/keyperf/keyperf_test.go b/cmd/collectors/keyperf/keyperf_test.go index 5cf51530d..c534edc54 100644 --- a/cmd/collectors/keyperf/keyperf_test.go +++ b/cmd/collectors/keyperf/keyperf_test.go @@ -187,7 +187,7 @@ func newKeyPerf(object string, path string) *KeyPerf { opts.HomePath = "testdata" opts.IsTest = true - ac := collector.New("KeyPerf", object, opts, params(object, path), nil) + ac := collector.New("KeyPerf", object, opts, params(object, path), nil, conf.Remote{}) kp := KeyPerf{} err = kp.Init(ac) if err != nil { diff --git a/cmd/collectors/ontap.go b/cmd/collectors/ontap.go new file mode 100644 index 000000000..05c313f61 --- /dev/null +++ b/cmd/collectors/ontap.go @@ -0,0 +1,103 @@ +package collectors + +import ( + "errors" + "github.com/netapp/harvest/v2/cmd/tools/rest" + "github.com/netapp/harvest/v2/pkg/api/ontapi/zapi" + "github.com/netapp/harvest/v2/pkg/auth" + "github.com/netapp/harvest/v2/pkg/conf" + "github.com/netapp/harvest/v2/pkg/errs" + "net/http" + "time" +) + +func GatherClusterInfo(pollerName string, cred *auth.Credentials) (conf.Remote, error) { + + var ( + err error + ) + + remoteZapi, err := checkZapi(pollerName, cred) + if err != nil { + return conf.Remote{}, err + } + + remoteRest, err := checkRest(pollerName, cred) + if err != nil { + return remoteZapi, err + } + + remoteRest.ZAPIsExist = remoteZapi.ZAPIsExist + + return remoteRest, nil +} + +func checkRest(pollerName string, cred *auth.Credentials) (conf.Remote, error) { + + var ( + poller *conf.Poller + client *rest.Client + err error + ) + + // connect to the cluster + if poller, err = conf.PollerNamed(pollerName); err != nil { + return conf.Remote{}, err + } + + timeout, _ := time.ParseDuration(rest.DefaultTimeout) + client, err = rest.New(poller, timeout, cred) + if err != nil { + return conf.Remote{}, err + } + + if err := client.Init(5, conf.Remote{}); err != nil { + return conf.Remote{}, err + } + + return client.Remote(), nil +} + +func checkZapi(pollerName string, cred *auth.Credentials) (conf.Remote, error) { + + var ( + poller *conf.Poller + client *zapi.Client + err error + zapisExist bool + ) + + // connect to the cluster and retrieve the system version + if poller, err = conf.PollerNamed(pollerName); err != nil { + return conf.Remote{}, err + } + if client, err = zapi.New(poller, cred); err != nil { + return conf.Remote{}, err + } + + zapisExist = true + err = client.Init(2, conf.Remote{}) + + if err != nil { + + returnErr := true + + var he errs.HarvestError + if errors.As(err, &he) { + switch { + case he.ErrNum == errs.ErrNumZAPISuspended, he.StatusCode == http.StatusBadRequest: + zapisExist = false + returnErr = false + } + } + + if returnErr { + return conf.Remote{}, err + } + } + + remote := client.Remote() + remote.ZAPIsExist = zapisExist + + return remote, nil +} diff --git a/cmd/collectors/power.go b/cmd/collectors/power.go index bdd39e687..95cceb758 100644 --- a/cmd/collectors/power.go +++ b/cmd/collectors/power.go @@ -440,7 +440,7 @@ type Sensor struct { hasREST bool } -func (s *Sensor) Init() error { +func (s *Sensor) Init(remote conf.Remote) error { var err error if err := s.InitAbc(); err != nil { @@ -455,7 +455,7 @@ func (s *Sensor) Init() error { s.hasREST = true - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { var re *errs.RestError if errors.As(err, &re) && re.StatusCode == http.StatusNotFound { s.SLogger.Warn("Cluster does not support REST. Power plugin disabled") diff --git a/cmd/collectors/rest/plugins/aggregate/aggregate.go b/cmd/collectors/rest/plugins/aggregate/aggregate.go index c747c2ac7..3dd974c48 100644 --- a/cmd/collectors/rest/plugins/aggregate/aggregate.go +++ b/cmd/collectors/rest/plugins/aggregate/aggregate.go @@ -36,7 +36,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Aggregate{AbstractPlugin: p} } -func (a *Aggregate) Init() error { +func (a *Aggregate) Init(remote conf.Remote) error { if err := a.InitAbc(); err != nil { return fmt.Errorf("failed to initialize AbstractPlugin: %w", err) } @@ -48,7 +48,7 @@ func (a *Aggregate) Init() error { } a.client = client - if err := a.client.Init(5); err != nil { + if err := a.client.Init(5, remote); err != nil { return fmt.Errorf("failed to initialize REST client: %w", err) } diff --git a/cmd/collectors/rest/plugins/certificate/certificate.go b/cmd/collectors/rest/plugins/certificate/certificate.go index d6bf7e001..7c8ed08f6 100644 --- a/cmd/collectors/rest/plugins/certificate/certificate.go +++ b/cmd/collectors/rest/plugins/certificate/certificate.go @@ -30,7 +30,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Certificate{AbstractPlugin: p} } -func (c *Certificate) Init() error { +func (c *Certificate) Init(remote conf.Remote) error { var err error @@ -44,7 +44,7 @@ func (c *Certificate) Init() error { return err } - if err := c.client.Init(5); err != nil { + if err := c.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/health/health.go b/cmd/collectors/rest/plugins/health/health.go index 3318c8d7d..6d488d881 100644 --- a/cmd/collectors/rest/plugins/health/health.go +++ b/cmd/collectors/rest/plugins/health/health.go @@ -58,7 +58,7 @@ var metrics = []string{ "alerts", } -func (h *Health) Init() error { +func (h *Health) Init(remote conf.Remote) error { var err error @@ -89,7 +89,7 @@ func (h *Health) Init() error { return err } - return h.client.Init(5) + return h.client.Init(5, remote) } func (h *Health) InitAllMatrix() error { diff --git a/cmd/collectors/rest/plugins/metroclustercheck/metroclustercheck.go b/cmd/collectors/rest/plugins/metroclustercheck/metroclustercheck.go index 5f4cc41bf..2a55ad684 100644 --- a/cmd/collectors/rest/plugins/metroclustercheck/metroclustercheck.go +++ b/cmd/collectors/rest/plugins/metroclustercheck/metroclustercheck.go @@ -2,6 +2,7 @@ package metroclustercheck import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/tree/node" @@ -19,7 +20,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &MetroclusterCheck{AbstractPlugin: p} } -func (m *MetroclusterCheck) Init() error { +func (m *MetroclusterCheck) Init(conf.Remote) error { pluginMetrics := []string{"cluster_status", "node_status", "aggr_status", "volume_status"} pluginLabels := []string{"result", "name", "node", "aggregate", "volume"} diff --git a/cmd/collectors/rest/plugins/netroute/netroute.go b/cmd/collectors/rest/plugins/netroute/netroute.go index 093aa890c..ed6ff3594 100644 --- a/cmd/collectors/rest/plugins/netroute/netroute.go +++ b/cmd/collectors/rest/plugins/netroute/netroute.go @@ -6,6 +6,7 @@ package netroute import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/tree/node" @@ -35,7 +36,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &NetRoute{AbstractPlugin: p} } -func (n *NetRoute) Init() error { +func (n *NetRoute) Init(conf.Remote) error { if err := n.InitAbc(); err != nil { return err diff --git a/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go b/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go index cc1555472..15ba7294d 100644 --- a/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go +++ b/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go @@ -29,7 +29,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &OntapS3Service{AbstractPlugin: p} } -func (o *OntapS3Service) Init() error { +func (o *OntapS3Service) Init(remote conf.Remote) error { var err error if err := o.InitAbc(); err != nil { @@ -49,7 +49,7 @@ func (o *OntapS3Service) Init() error { return err } - if err := o.client.Init(5); err != nil { + if err := o.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/quota/quota.go b/cmd/collectors/rest/plugins/quota/quota.go index 66583ec75..2501d5a1e 100644 --- a/cmd/collectors/rest/plugins/quota/quota.go +++ b/cmd/collectors/rest/plugins/quota/quota.go @@ -2,6 +2,7 @@ package quota import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/util" @@ -17,7 +18,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Quota{AbstractPlugin: p} } -func (q *Quota) Init() error { +func (q *Quota) Init(conf.Remote) error { if err := q.InitAbc(); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/securityaccount/securityaccount.go b/cmd/collectors/rest/plugins/securityaccount/securityaccount.go index b0dd58fc8..923dfca4e 100644 --- a/cmd/collectors/rest/plugins/securityaccount/securityaccount.go +++ b/cmd/collectors/rest/plugins/securityaccount/securityaccount.go @@ -28,7 +28,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SecurityAccount{AbstractPlugin: p} } -func (s *SecurityAccount) Init() error { +func (s *SecurityAccount) Init(remote conf.Remote) error { var err error if err := s.InitAbc(); err != nil { @@ -47,7 +47,7 @@ func (s *SecurityAccount) Init() error { return fmt.Errorf("failed to connect err=%w", err) } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/shelf/shelf.go b/cmd/collectors/rest/plugins/shelf/shelf.go index 2d2e4940f..1d78750cf 100644 --- a/cmd/collectors/rest/plugins/shelf/shelf.go +++ b/cmd/collectors/rest/plugins/shelf/shelf.go @@ -4,6 +4,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/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/util" ) @@ -16,7 +17,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Shelf{AbstractPlugin: p} } -func (my *Shelf) Init() error { +func (my *Shelf) Init(conf.Remote) error { return my.InitAbc() } diff --git a/cmd/collectors/rest/plugins/snapmirror/snapmirror.go b/cmd/collectors/rest/plugins/snapmirror/snapmirror.go index 2ca13a577..0b133876a 100644 --- a/cmd/collectors/rest/plugins/snapmirror/snapmirror.go +++ b/cmd/collectors/rest/plugins/snapmirror/snapmirror.go @@ -40,7 +40,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SnapMirror{AbstractPlugin: p} } -func (m *SnapMirror) Init() error { +func (m *SnapMirror) Init(remote conf.Remote) error { var err error @@ -54,7 +54,7 @@ func (m *SnapMirror) Init() error { return err } - if err := m.client.Init(5); err != nil { + if err := m.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/svm/svm.go b/cmd/collectors/rest/plugins/svm/svm.go index d05887b93..3d04a8c58 100644 --- a/cmd/collectors/rest/plugins/svm/svm.go +++ b/cmd/collectors/rest/plugins/svm/svm.go @@ -48,7 +48,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SVM{AbstractPlugin: p} } -func (s *SVM) Init() error { +func (s *SVM) Init(remote conf.Remote) error { var err error @@ -62,7 +62,7 @@ func (s *SVM) Init() error { return err } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } s.nsswitchInfo = make(map[string]Nsswitch) diff --git a/cmd/collectors/rest/plugins/volume/volume.go b/cmd/collectors/rest/plugins/volume/volume.go index cbc7d24c2..d3ccda20f 100644 --- a/cmd/collectors/rest/plugins/volume/volume.go +++ b/cmd/collectors/rest/plugins/volume/volume.go @@ -52,7 +52,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } -func (v *Volume) Init() error { +func (v *Volume) Init(remote conf.Remote) error { var err error @@ -75,7 +75,7 @@ func (v *Volume) Init() error { return err } - if err := v.client.Init(5); err != nil { + if err := v.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go b/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go index 197e50464..e0444def4 100644 --- a/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go +++ b/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go @@ -38,7 +38,7 @@ var metrics = []string{ "dir_subdir_count", } -func (v *VolumeAnalytics) Init() error { +func (v *VolumeAnalytics) Init(remote conf.Remote) error { var err error @@ -67,7 +67,7 @@ func (v *VolumeAnalytics) Init() error { return err } - if err := v.client.Init(5); err != nil { + if err := v.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/rest/plugins/workload/workload.go b/cmd/collectors/rest/plugins/workload/workload.go index 67c70365e..9b2488d97 100644 --- a/cmd/collectors/rest/plugins/workload/workload.go +++ b/cmd/collectors/rest/plugins/workload/workload.go @@ -3,6 +3,7 @@ package workload import ( "github.com/netapp/harvest/v2/cmd/collectors" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/util" @@ -22,7 +23,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Workload{AbstractPlugin: p} } -func (w *Workload) Init() error { +func (w *Workload) Init(conf.Remote) error { if err := w.InitAbc(); err != nil { return err } diff --git a/cmd/collectors/rest/rest.go b/cmd/collectors/rest/rest.go index 0fd69c96c..96a5bd450 100644 --- a/cmd/collectors/rest/rest.go +++ b/cmd/collectors/rest/rest.go @@ -196,12 +196,12 @@ func (r *Rest) InitClient() error { if r.Options.IsTest { return nil } - if err := r.Client.Init(5); err != nil { + + if err := r.Client.Init(5, r.Remote); err != nil { return err } - r.Client.TraceLogSet(r.Name, r.Params) - r.Remote = r.Client.Remote() + r.Client.TraceLogSet(r.Name, r.Params) return nil } diff --git a/cmd/collectors/rest/rest_test.go b/cmd/collectors/rest/rest_test.go index bb23d1db7..01391086f 100644 --- a/cmd/collectors/rest/rest_test.go +++ b/cmd/collectors/rest/rest_test.go @@ -155,7 +155,7 @@ func newRest(object string, path string, confPath string) *Rest { opts.Poller = pollerName opts.HomePath = "testdata" opts.IsTest = true - ac := collector.New("Rest", object, opts, collectors.Params(object, path), nil) + ac := collector.New("Rest", object, opts, collectors.Params(object, path), nil, conf.Remote{}) r := Rest{} err = r.Init(ac) if err != nil { diff --git a/cmd/collectors/restperf/plugins/disk/disk.go b/cmd/collectors/restperf/plugins/disk/disk.go index c0d291407..4ff4bc2e8 100644 --- a/cmd/collectors/restperf/plugins/disk/disk.go +++ b/cmd/collectors/restperf/plugins/disk/disk.go @@ -108,7 +108,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Disk{AbstractPlugin: p} } -func (d *Disk) Init() error { +func (d *Disk) Init(remote conf.Remote) error { var err error if err := d.InitAbc(); err != nil { @@ -121,7 +121,7 @@ func (d *Disk) Init() error { return err } - if err := d.client.Init(5); err != nil { + if err := d.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go b/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go index b2d968c8b..12a57b603 100644 --- a/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go +++ b/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go @@ -3,6 +3,7 @@ package fabricpool import ( "github.com/netapp/harvest/v2/cmd/collectors" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/util" "strconv" @@ -18,7 +19,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FabricPool{AbstractPlugin: p} } -func (f *FabricPool) Init() error { +func (f *FabricPool) Init(conf.Remote) error { err := f.InitAbc() if err != nil { return err diff --git a/cmd/collectors/restperf/plugins/fcvi/fcvi.go b/cmd/collectors/restperf/plugins/fcvi/fcvi.go index 8ab00f90e..8a3fd5aa0 100644 --- a/cmd/collectors/restperf/plugins/fcvi/fcvi.go +++ b/cmd/collectors/restperf/plugins/fcvi/fcvi.go @@ -21,7 +21,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FCVI{AbstractPlugin: p} } -func (f *FCVI) Init() error { +func (f *FCVI) Init(remote conf.Remote) error { var err error if err := f.InitAbc(); err != nil { return err @@ -33,7 +33,7 @@ func (f *FCVI) Init() error { return err } - return f.client.Init(5) + return f.client.Init(5, remote) } func (f *FCVI) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/restperf/plugins/nic/nic.go b/cmd/collectors/restperf/plugins/nic/nic.go index 33d2a687c..122edd535 100644 --- a/cmd/collectors/restperf/plugins/nic/nic.go +++ b/cmd/collectors/restperf/plugins/nic/nic.go @@ -46,7 +46,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Nic{AbstractPlugin: p} } -func (n *Nic) Init() error { +func (n *Nic) Init(remote conf.Remote) error { err := n.InitAbc() if err != nil { return err @@ -80,7 +80,7 @@ func (n *Nic) Init() error { return err } - if err := n.client.Init(5); err != nil { + if err := n.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/restperf/plugins/nic/nic_test.go b/cmd/collectors/restperf/plugins/nic/nic_test.go index 7d95b9697..0172dd119 100644 --- a/cmd/collectors/restperf/plugins/nic/nic_test.go +++ b/cmd/collectors/restperf/plugins/nic/nic_test.go @@ -4,6 +4,7 @@ import ( "github.com/netapp/harvest/v2/cmd/poller/options" "github.com/netapp/harvest/v2/cmd/poller/plugin" "github.com/netapp/harvest/v2/cmd/tools/rest" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "github.com/netapp/harvest/v2/pkg/util" @@ -17,7 +18,7 @@ func runNicTest(t *testing.T, createRestNic func(params *node.Node) plugin.Plugi n := createRestNic(params) // Initialize the plugin - if err := n.Init(); err != nil { + if err := n.Init(conf.Remote{}); err != nil { t.Fatalf("failed to initialize plugin: %v", err) } diff --git a/cmd/collectors/restperf/plugins/volume/volume.go b/cmd/collectors/restperf/plugins/volume/volume.go index c66186073..61438373e 100644 --- a/cmd/collectors/restperf/plugins/volume/volume.go +++ b/cmd/collectors/restperf/plugins/volume/volume.go @@ -24,7 +24,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } -func (v *Volume) Init() error { +func (v *Volume) Init(remote conf.Remote) error { var err error if err := v.InitAbc(); err != nil { return err @@ -55,7 +55,7 @@ func (v *Volume) Init() error { return err } - return v.client.Init(5) + return v.client.Init(5, remote) } func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/restperf/plugins/volume/volume_test.go b/cmd/collectors/restperf/plugins/volume/volume_test.go index 513232584..6bd971e87 100644 --- a/cmd/collectors/restperf/plugins/volume/volume_test.go +++ b/cmd/collectors/restperf/plugins/volume/volume_test.go @@ -5,6 +5,7 @@ import ( volume2 "github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/volume" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/volume" "github.com/netapp/harvest/v2/cmd/poller/options" + "github.com/netapp/harvest/v2/pkg/conf" "log/slog" "strconv" "testing" @@ -26,7 +27,7 @@ func runVolumeTest(t *testing.T, createVolume func(params *node.Node) plugin.Plu volumesMap := make(map[string]string) // Initialize the plugin - if err := v.Init(); err != nil { + if err := v.Init(conf.Remote{}); err != nil { t.Fatalf("failed to initialize plugin: %v", err) } diff --git a/cmd/collectors/restperf/plugins/volumetag/volumetag.go b/cmd/collectors/restperf/plugins/volumetag/volumetag.go index 501136514..56a4d3e6d 100644 --- a/cmd/collectors/restperf/plugins/volumetag/volumetag.go +++ b/cmd/collectors/restperf/plugins/volumetag/volumetag.go @@ -21,7 +21,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &VolumeTag{AbstractPlugin: p} } -func (v *VolumeTag) Init() error { +func (v *VolumeTag) Init(remote conf.Remote) error { var err error if err := v.InitAbc(); err != nil { return err @@ -33,7 +33,7 @@ func (v *VolumeTag) Init() error { return err } - return v.client.Init(5) + return v.client.Init(5, remote) } func (v *VolumeTag) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go index 082de6e12..a8c77e508 100644 --- a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go +++ b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go @@ -97,7 +97,7 @@ func (t *TopClients) initMatrix(name string, object string, inputMat map[string] return nil } -func (t *TopClients) Init() error { +func (t *TopClients) Init(remote conf.Remote) error { var err error if err := t.InitAbc(); err != nil { return err @@ -112,7 +112,7 @@ func (t *TopClients) Init() error { return err } - if err := t.client.Init(5); err != nil { + if err := t.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/restperf/restperf_test.go b/cmd/collectors/restperf/restperf_test.go index 172db83bd..a668ad644 100644 --- a/cmd/collectors/restperf/restperf_test.go +++ b/cmd/collectors/restperf/restperf_test.go @@ -353,7 +353,7 @@ func newRestPerf(object string, path string) *RestPerf { opts.HomePath = "testdata" opts.IsTest = true - ac := collector.New("RestPerf", object, opts, params(object, path), nil) + ac := collector.New("RestPerf", object, opts, params(object, path), nil, conf.Remote{}) r := RestPerf{} err = r.Init(ac) if err != nil { diff --git a/cmd/collectors/storagegrid/plugins/bucket/bucket.go b/cmd/collectors/storagegrid/plugins/bucket/bucket.go index b4d34980e..db823d70b 100644 --- a/cmd/collectors/storagegrid/plugins/bucket/bucket.go +++ b/cmd/collectors/storagegrid/plugins/bucket/bucket.go @@ -3,6 +3,7 @@ package bucket import ( "github.com/netapp/harvest/v2/cmd/collectors/storagegrid/rest" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/util" @@ -20,7 +21,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Bucket{AbstractPlugin: p} } -func (b *Bucket) Init() error { +func (b *Bucket) Init(remote conf.Remote) error { var err error @@ -34,7 +35,7 @@ func (b *Bucket) Init() error { return err } - if err := b.client.Init(5); err != nil { + if err := b.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go b/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go index 81f5ebb14..f6f9dd7e0 100644 --- a/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go +++ b/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go @@ -3,6 +3,7 @@ package joinrest import ( "github.com/netapp/harvest/v2/cmd/collectors/storagegrid/rest" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/util" @@ -40,13 +41,13 @@ plugins: label_prom: policy ` -func (t *JoinRest) Init() error { +func (t *JoinRest) Init(remote conf.Remote) error { var err error if err := t.InitAbc(); err != nil { return err } - if err := t.initClient(); err != nil { + if err := t.initClient(remote); err != nil { return err } @@ -164,14 +165,14 @@ func (t *JoinRest) updateCache(model join, bytes *[]byte) { } } -func (t *JoinRest) initClient() error { +func (t *JoinRest) initClient(remote conf.Remote) error { var err error if t.client, err = rest.NewClient(t.Options.Poller, t.Params.GetChildContentS("client_timeout"), t.Auth); err != nil { return err } - if err := t.client.Init(5); err != nil { + if err := t.client.Init(5, remote); err != nil { return err } t.client.TraceLogSet(t.Name, t.Params) diff --git a/cmd/collectors/storagegrid/rest/client.go b/cmd/collectors/storagegrid/rest/client.go index 1f8887572..cac805eb8 100644 --- a/cmd/collectors/storagegrid/rest/client.go +++ b/cmd/collectors/storagegrid/rest/client.go @@ -268,12 +268,18 @@ func (c *Client) fetch() ([]byte, error) { } // Init is responsible for determining the StorageGrid server version, API version, hostname, and systemId -func (c *Client) Init(retries int) error { +func (c *Client) Init(retries int, remote conf.Remote) error { var ( err error content []byte ) + c.Remote = remote + + if !remote.IsZero() { + return nil + } + for range retries { // Determine which API versions are supported and then request // product version and cluster name - both of which are separate endpoints diff --git a/cmd/collectors/storagegrid/storagegrid.go b/cmd/collectors/storagegrid/storagegrid.go index 0eb215388..d6e74ac43 100644 --- a/cmd/collectors/storagegrid/storagegrid.go +++ b/cmd/collectors/storagegrid/storagegrid.go @@ -437,13 +437,11 @@ func (s *StorageGrid) initClient() error { return nil } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, s.Remote); err != nil { return err } s.client.TraceLogSet(s.Name, s.Params) - s.Remote = s.client.Remote - return nil } diff --git a/cmd/collectors/storagegrid/storagegrid_test.go b/cmd/collectors/storagegrid/storagegrid_test.go index 9be1cc376..6bb04de4d 100644 --- a/cmd/collectors/storagegrid/storagegrid_test.go +++ b/cmd/collectors/storagegrid/storagegrid_test.go @@ -26,7 +26,7 @@ func newStorageGrid(object string, path string) (*StorageGrid, error) { rest.NewClientFunc = func(_ string, _ string, _ *auth.Credentials) (*rest.Client, error) { return rest.NewDummyClient(), nil } - ac := collector.New("StorageGrid", object, opts, collectors.Params(object, path), nil) + ac := collector.New("StorageGrid", object, opts, collectors.Params(object, path), nil, conf.Remote{}) err := r.Init(ac) if err != nil { return nil, err diff --git a/cmd/collectors/zapi/collector/zapi.go b/cmd/collectors/zapi/collector/zapi.go index a332ebfa8..6d735fead 100644 --- a/cmd/collectors/zapi/collector/zapi.go +++ b/cmd/collectors/zapi/collector/zapi.go @@ -107,7 +107,7 @@ func (z *Zapi) InitVars() error { } z.Client.TraceLogSet(z.Name, z.Params) - if err = z.Client.Init(5); err != nil { // 5 retries before giving up to connect + if err = z.Client.Init(5, z.Remote); err != nil { // 5 retries before giving up to connect return errs.New(errs.ErrConnection, err.Error()) } z.Logger.Debug("connected", slog.String("client", z.Client.Info())) @@ -117,15 +117,6 @@ func (z *Zapi) InitVars() error { model = "7mode" } - // save for ASUP messaging - versionT := z.Client.Version() - z.Remote = conf.Remote{ - Name: z.Client.Name(), - UUID: z.Client.Serial(), - Model: model, - Version: strconv.Itoa(versionT[0]) + "." + strconv.Itoa(versionT[1]) + "." + strconv.Itoa(versionT[2]), - } - templateName := z.Params.GetChildS("objects").GetChildContentS(z.Object) template, path, err := z.ImportSubTemplate(model, templateName, jitter, z.Remote.Version) if err != nil { diff --git a/cmd/collectors/zapi/plugins/aggregate/aggregate.go b/cmd/collectors/zapi/plugins/aggregate/aggregate.go index ead36c95b..1624c20b6 100644 --- a/cmd/collectors/zapi/plugins/aggregate/aggregate.go +++ b/cmd/collectors/zapi/plugins/aggregate/aggregate.go @@ -27,7 +27,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Aggregate{AbstractPlugin: p} } -func (a *Aggregate) Init() error { +func (a *Aggregate) Init(remote conf.Remote) error { var err error @@ -40,7 +40,7 @@ func (a *Aggregate) Init() error { return err } - if err := a.client.Init(5); err != nil { + if err := a.client.Init(5, remote); err != nil { return err } @@ -109,8 +109,7 @@ func (a *Aggregate) getCloudStores() error { ) // aggr-object-store-get-iter Zapi was introduced in 9.2. - version := a.client.Version() - clusterVersion := strconv.Itoa(version[0]) + "." + strconv.Itoa(version[1]) + "." + strconv.Itoa(version[2]) + clusterVersion := a.client.Version() ontapVersion, err := goversion.NewVersion(clusterVersion) if err != nil { a.SLogger.Error( diff --git a/cmd/collectors/zapi/plugins/certificate/certificate.go b/cmd/collectors/zapi/plugins/certificate/certificate.go index d1210cf7d..68518399a 100644 --- a/cmd/collectors/zapi/plugins/certificate/certificate.go +++ b/cmd/collectors/zapi/plugins/certificate/certificate.go @@ -34,7 +34,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Certificate{AbstractPlugin: p} } -func (c *Certificate) Init() error { +func (c *Certificate) Init(remote conf.Remote) error { var err error @@ -47,7 +47,7 @@ func (c *Certificate) Init() error { return err } - if err := c.client.Init(5); err != nil { + if err := c.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/qtree/qtree.go b/cmd/collectors/zapi/plugins/qtree/qtree.go index 23ba04552..80d05662b 100644 --- a/cmd/collectors/zapi/plugins/qtree/qtree.go +++ b/cmd/collectors/zapi/plugins/qtree/qtree.go @@ -38,7 +38,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Qtree{AbstractPlugin: p} } -func (q *Qtree) Init() error { +func (q *Qtree) Init(remote conf.Remote) error { var err error @@ -55,7 +55,7 @@ func (q *Qtree) Init() error { return err } - if err := q.client.Init(5); err != nil { + if err := q.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/qtree/qtree_test.go b/cmd/collectors/zapi/plugins/qtree/qtree_test.go index 1ad397106..77b2ec0ea 100644 --- a/cmd/collectors/zapi/plugins/qtree/qtree_test.go +++ b/cmd/collectors/zapi/plugins/qtree/qtree_test.go @@ -4,6 +4,7 @@ import ( "github.com/netapp/harvest/v2/cmd/poller/options" "github.com/netapp/harvest/v2/cmd/poller/plugin" client "github.com/netapp/harvest/v2/pkg/api/ontapi/zapi" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "log/slog" @@ -108,7 +109,7 @@ func runQtreeTest(t *testing.T, createQtree func(historicalLabels bool) plugin.P q := createQtree(historicalLabels) // Initialize the plugin - if err := q.Init(); err != nil { + if err := q.Init(conf.Remote{}); err != nil { t.Fatalf("failed to initialize plugin: %v", err) } diff --git a/cmd/collectors/zapi/plugins/security/security.go b/cmd/collectors/zapi/plugins/security/security.go index 4d0353004..54a1eb9c9 100644 --- a/cmd/collectors/zapi/plugins/security/security.go +++ b/cmd/collectors/zapi/plugins/security/security.go @@ -28,7 +28,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Security{AbstractPlugin: p} } -func (s *Security) Init() error { +func (s *Security) Init(remote conf.Remote) error { var err error @@ -41,7 +41,7 @@ func (s *Security) Init() error { return err } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/shelf/shelf.go b/cmd/collectors/zapi/plugins/shelf/shelf.go index 41ba48bea..23d457c0e 100644 --- a/cmd/collectors/zapi/plugins/shelf/shelf.go +++ b/cmd/collectors/zapi/plugins/shelf/shelf.go @@ -40,7 +40,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Shelf{AbstractPlugin: p} } -func (s *Shelf) Init() error { +func (s *Shelf) Init(remote conf.Remote) error { var err error @@ -53,7 +53,7 @@ func (s *Shelf) Init() error { return err } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/snapmirror/snapmirror.go b/cmd/collectors/zapi/plugins/snapmirror/snapmirror.go index 68d902cb2..68fef0ba5 100644 --- a/cmd/collectors/zapi/plugins/snapmirror/snapmirror.go +++ b/cmd/collectors/zapi/plugins/snapmirror/snapmirror.go @@ -36,7 +36,8 @@ var flexgroupConstituentName = regexp.MustCompile(`^(.*)__(\d{4})$`) func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SnapMirror{AbstractPlugin: p} } -func (m *SnapMirror) Init() error { + +func (m *SnapMirror) Init(remote conf.Remote) error { var err error if err := m.InitAbc(); err != nil { return err @@ -45,7 +46,7 @@ func (m *SnapMirror) Init() error { m.SLogger.Error("connecting", slogx.Err(err)) return err } - if err := m.client.Init(5); err != nil { + if err := m.client.Init(5, remote); err != nil { return err } m.nodeUpdCounter = 0 diff --git a/cmd/collectors/zapi/plugins/svm/svm.go b/cmd/collectors/zapi/plugins/svm/svm.go index e8eacd387..97fe821e2 100644 --- a/cmd/collectors/zapi/plugins/svm/svm.go +++ b/cmd/collectors/zapi/plugins/svm/svm.go @@ -70,7 +70,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SVM{AbstractPlugin: p} } -func (s *SVM) Init() error { +func (s *SVM) Init(remote conf.Remote) error { var err error @@ -83,7 +83,7 @@ func (s *SVM) Init() error { return err } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/systemnode/systemnode.go b/cmd/collectors/zapi/plugins/systemnode/systemnode.go index b04440fdc..6945964a2 100644 --- a/cmd/collectors/zapi/plugins/systemnode/systemnode.go +++ b/cmd/collectors/zapi/plugins/systemnode/systemnode.go @@ -20,7 +20,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &SystemNode{AbstractPlugin: p} } -func (s *SystemNode) Init() error { +func (s *SystemNode) Init(remote conf.Remote) error { var err error @@ -33,7 +33,7 @@ func (s *SystemNode) Init() error { return err } - if err := s.client.Init(5); err != nil { + if err := s.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/volume/volume.go b/cmd/collectors/zapi/plugins/volume/volume.go index 27a5b740a..a9ca97d99 100644 --- a/cmd/collectors/zapi/plugins/volume/volume.go +++ b/cmd/collectors/zapi/plugins/volume/volume.go @@ -36,7 +36,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } -func (v *Volume) Init() error { +func (v *Volume) Init(remote conf.Remote) error { var err error @@ -50,7 +50,7 @@ func (v *Volume) Init() error { return err } - if err := v.client.Init(5); err != nil { + if err := v.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapi/plugins/workload/workload.go b/cmd/collectors/zapi/plugins/workload/workload.go index 67c70365e..9b2488d97 100644 --- a/cmd/collectors/zapi/plugins/workload/workload.go +++ b/cmd/collectors/zapi/plugins/workload/workload.go @@ -3,6 +3,7 @@ package workload import ( "github.com/netapp/harvest/v2/cmd/collectors" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" "github.com/netapp/harvest/v2/pkg/util" @@ -22,7 +23,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Workload{AbstractPlugin: p} } -func (w *Workload) Init() error { +func (w *Workload) Init(conf.Remote) error { if err := w.InitAbc(); err != nil { return err } diff --git a/cmd/collectors/zapiperf/plugins/disk/disk.go b/cmd/collectors/zapiperf/plugins/disk/disk.go index fe2d73059..7a1862f9a 100644 --- a/cmd/collectors/zapiperf/plugins/disk/disk.go +++ b/cmd/collectors/zapiperf/plugins/disk/disk.go @@ -109,7 +109,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Disk{AbstractPlugin: p} } -func (d *Disk) Init() error { +func (d *Disk) Init(remote conf.Remote) error { var err error @@ -122,7 +122,7 @@ func (d *Disk) Init() error { return err } - if err := d.client.Init(5); err != nil { + if err := d.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go b/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go index 9ff3497ad..dc8bd95ae 100644 --- a/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go +++ b/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go @@ -3,6 +3,7 @@ package fabricpool import ( "github.com/netapp/harvest/v2/cmd/collectors" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/util" "strconv" @@ -17,7 +18,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FabricPool{AbstractPlugin: p} } -func (f *FabricPool) Init() error { +func (f *FabricPool) Init(conf.Remote) error { err := f.InitAbc() if err != nil { return err diff --git a/cmd/collectors/zapiperf/plugins/fcvi/fcvi.go b/cmd/collectors/zapiperf/plugins/fcvi/fcvi.go index 4f7abf5c7..5b654d5d3 100644 --- a/cmd/collectors/zapiperf/plugins/fcvi/fcvi.go +++ b/cmd/collectors/zapiperf/plugins/fcvi/fcvi.go @@ -23,7 +23,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FCVI{AbstractPlugin: p} } -func (f *FCVI) Init() error { +func (f *FCVI) Init(remote conf.Remote) error { var err error if err := f.InitAbc(); err != nil { return err @@ -33,7 +33,7 @@ func (f *FCVI) Init() error { f.SLogger.Error("connecting", slogx.Err(err)) return err } - return f.client.Init(5) + return f.client.Init(5, remote) } func (f *FCVI) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/zapiperf/plugins/flexcache/flexcache.go b/cmd/collectors/zapiperf/plugins/flexcache/flexcache.go index 4c14781bd..541331dba 100644 --- a/cmd/collectors/zapiperf/plugins/flexcache/flexcache.go +++ b/cmd/collectors/zapiperf/plugins/flexcache/flexcache.go @@ -25,7 +25,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FlexCache{AbstractPlugin: p} } -func (f *FlexCache) Init() error { +func (f *FlexCache) Init(remote conf.Remote) error { var err error @@ -38,7 +38,7 @@ func (f *FlexCache) Init() error { return err } - if err := f.client.Init(5); err != nil { + if err := f.client.Init(5, remote); err != nil { return err } return nil diff --git a/cmd/collectors/zapiperf/plugins/nic/nic.go b/cmd/collectors/zapiperf/plugins/nic/nic.go index 7467b3990..3dcc2db3f 100644 --- a/cmd/collectors/zapiperf/plugins/nic/nic.go +++ b/cmd/collectors/zapiperf/plugins/nic/nic.go @@ -47,7 +47,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Nic{AbstractPlugin: p} } -func (n *Nic) Init() error { +func (n *Nic) Init(remote conf.Remote) error { var err error if err := n.InitAbc(); err != nil { return err @@ -58,7 +58,7 @@ func (n *Nic) Init() error { return err } - if err := n.client.Init(5); err != nil { + if err := n.client.Init(5, remote); err != nil { return err } diff --git a/cmd/collectors/zapiperf/plugins/volume/volume.go b/cmd/collectors/zapiperf/plugins/volume/volume.go index 5af6eaea5..d70a06f03 100644 --- a/cmd/collectors/zapiperf/plugins/volume/volume.go +++ b/cmd/collectors/zapiperf/plugins/volume/volume.go @@ -30,7 +30,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } -func (v *Volume) Init() error { +func (v *Volume) Init(remote conf.Remote) error { var err error if err := v.InitAbc(); err != nil { return err @@ -58,7 +58,7 @@ func (v *Volume) Init() error { v.SLogger.Error("connecting", slog.Any("err", err)) return err } - return v.client.Init(5) + return v.client.Init(5, remote) } func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/zapiperf/plugins/volumetag/volumetag.go b/cmd/collectors/zapiperf/plugins/volumetag/volumetag.go index 16f32113f..820283462 100644 --- a/cmd/collectors/zapiperf/plugins/volumetag/volumetag.go +++ b/cmd/collectors/zapiperf/plugins/volumetag/volumetag.go @@ -21,7 +21,7 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { return &VolumeTag{AbstractPlugin: p} } -func (v *VolumeTag) Init() error { +func (v *VolumeTag) Init(remote conf.Remote) error { var err error if err := v.InitAbc(); err != nil { return err @@ -31,7 +31,7 @@ func (v *VolumeTag) Init() error { v.SLogger.Error("connecting", slogx.Err(err)) return err } - return v.client.Init(5) + return v.client.Init(5, remote) } func (v *VolumeTag) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) { diff --git a/cmd/collectors/zapiperf/zapiperf_test.go b/cmd/collectors/zapiperf/zapiperf_test.go index 51b735ba6..61ae5dc0c 100644 --- a/cmd/collectors/zapiperf/zapiperf_test.go +++ b/cmd/collectors/zapiperf/zapiperf_test.go @@ -189,7 +189,7 @@ func NewZapiPerf(object, path string) *ZapiPerf { opts.HomePath = homePath opts.IsTest = true - ac := collector.New("Zapiperf", object, opts, params(object, path), nil) + ac := collector.New("Zapiperf", object, opts, params(object, path), nil, conf.Remote{}) z := &ZapiPerf{} if err := z.Init(ac); err != nil { slog.Error("", slogx.Err(err)) diff --git a/cmd/poller/collector/collector.go b/cmd/poller/collector/collector.go index d4bc6d6fc..0b6ae3f90 100644 --- a/cmd/poller/collector/collector.go +++ b/cmd/poller/collector/collector.go @@ -113,7 +113,7 @@ type AbstractCollector struct { Remote conf.Remote } -func New(name, object string, o *options.Options, params *node.Node, credentials *auth.Credentials) *AbstractCollector { +func New(name, object string, o *options.Options, params *node.Node, credentials *auth.Credentials, remote conf.Remote) *AbstractCollector { return &AbstractCollector{ Name: name, Object: object, @@ -122,6 +122,7 @@ func New(name, object string, o *options.Options, params *node.Node, credentials Params: params, countMux: &sync.Mutex{}, Auth: credentials, + Remote: remote, } } @@ -758,7 +759,7 @@ func (c *AbstractCollector) LoadPlugins(params *node.Node, collector Collector, continue } - if err := p.Init(); err != nil { + if err := p.Init(c.Remote); err != nil { slog.Error("init plugin", slogx.Err(err), slog.String("name", name)) return err } diff --git a/cmd/poller/plugin/aggregator/aggregator.go b/cmd/poller/plugin/aggregator/aggregator.go index 6f5044757..784fad294 100644 --- a/cmd/poller/plugin/aggregator/aggregator.go +++ b/cmd/poller/plugin/aggregator/aggregator.go @@ -7,6 +7,7 @@ package aggregator import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" @@ -38,9 +39,9 @@ type rule struct { counts map[string]map[string]float64 } -func (a *Aggregator) Init() error { +func (a *Aggregator) Init(remote conf.Remote) error { - if err := a.AbstractPlugin.Init(); err != nil { + if err := a.AbstractPlugin.Init(remote); err != nil { return err } diff --git a/cmd/poller/plugin/aggregator/aggregator_test.go b/cmd/poller/plugin/aggregator/aggregator_test.go index f8a6ed34e..9373d1b63 100644 --- a/cmd/poller/plugin/aggregator/aggregator_test.go +++ b/cmd/poller/plugin/aggregator/aggregator_test.go @@ -6,6 +6,7 @@ package aggregator import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "testing" @@ -18,7 +19,7 @@ func newAggregator() *Aggregator { abc := plugin.New("Test", nil, params, nil, "", nil) p := &Aggregator{AbstractPlugin: abc} - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { panic(err) } return p @@ -94,7 +95,7 @@ func TestRuleIncludeAllLabels(t *testing.T) { p.Params = params - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { t.Fatal(err) } @@ -156,7 +157,7 @@ func TestComplexRuleRegex(t *testing.T) { p.Params = params m := newArtificialData() - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { t.Fatal(err) } @@ -313,7 +314,7 @@ func TestRuleSimpleLatencyAggregation(t *testing.T) { p.Params = params - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { t.Fatal(err) } @@ -421,7 +422,7 @@ func TestRuleSimpleLatencyZeroAggregation(t *testing.T) { p.Params = params - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { t.Fatal(err) } diff --git a/cmd/poller/plugin/changelog/changelog.go b/cmd/poller/plugin/changelog/changelog.go index e209f8043..b59744a60 100644 --- a/cmd/poller/plugin/changelog/changelog.go +++ b/cmd/poller/plugin/changelog/changelog.go @@ -2,6 +2,7 @@ package changelog import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/set" "github.com/netapp/harvest/v2/pkg/tree/yaml" @@ -68,10 +69,10 @@ func New(p *plugin.AbstractPlugin) plugin.Plugin { } // Init initializes the ChangeLog plugin -func (c *ChangeLog) Init() error { +func (c *ChangeLog) Init(remote conf.Remote) error { // Initialize the abstract plugin - if err := c.AbstractPlugin.Init(); err != nil { + if err := c.AbstractPlugin.Init(remote); err != nil { return err } diff --git a/cmd/poller/plugin/changelog/changelog_test.go b/cmd/poller/plugin/changelog/changelog_test.go index 2f503d5b3..057b90492 100644 --- a/cmd/poller/plugin/changelog/changelog_test.go +++ b/cmd/poller/plugin/changelog/changelog_test.go @@ -3,6 +3,7 @@ package changelog import ( "github.com/netapp/harvest/v2/cmd/poller/options" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "testing" @@ -31,7 +32,7 @@ func createChangeLog(params, parentParams *node.Node) *ChangeLog { } p.Object = "svm" - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { panic(err) } return p diff --git a/cmd/poller/plugin/labelagent/label_agent.go b/cmd/poller/plugin/labelagent/label_agent.go index da57ad061..49afa29f5 100644 --- a/cmd/poller/plugin/labelagent/label_agent.go +++ b/cmd/poller/plugin/labelagent/label_agent.go @@ -7,6 +7,7 @@ package labelagent import ( "fmt" "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" @@ -39,14 +40,14 @@ func New(p *plugin.AbstractPlugin) *LabelAgent { return &LabelAgent{AbstractPlugin: p} } -func (a *LabelAgent) Init() error { +func (a *LabelAgent) Init(remote conf.Remote) error { var ( err error count int ) - if err := a.AbstractPlugin.Init(); err != nil { + if err := a.AbstractPlugin.Init(remote); err != nil { return err } diff --git a/cmd/poller/plugin/labelagent/label_agent_test.go b/cmd/poller/plugin/labelagent/label_agent_test.go index 0f146d513..81ead6397 100644 --- a/cmd/poller/plugin/labelagent/label_agent_test.go +++ b/cmd/poller/plugin/labelagent/label_agent_test.go @@ -6,6 +6,7 @@ package labelagent import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "testing" @@ -67,7 +68,7 @@ func newLabelAgent() *LabelAgent { abc := plugin.New("Test", nil, params, nil, "", nil) p := &LabelAgent{AbstractPlugin: abc} - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { panic(err) } return p @@ -93,7 +94,7 @@ func TestSplitRegexQtree(t *testing.T) { abc := plugin.New("Test", nil, params, nil, "", nil) p := &LabelAgent{AbstractPlugin: abc} - err := p.Init() + err := p.Init(conf.Remote{}) if err != nil { panic(err) } diff --git a/cmd/poller/plugin/max/max.go b/cmd/poller/plugin/max/max.go index d3a46948c..62ac94ec2 100644 --- a/cmd/poller/plugin/max/max.go +++ b/cmd/poller/plugin/max/max.go @@ -6,6 +6,7 @@ package max import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" @@ -36,9 +37,9 @@ type rule struct { counts map[string]map[string]int } -func (m *Max) Init() error { +func (m *Max) Init(remote conf.Remote) error { - if err := m.AbstractPlugin.Init(); err != nil { + if err := m.AbstractPlugin.Init(remote); err != nil { return err } diff --git a/cmd/poller/plugin/metricagent/metric_agent.go b/cmd/poller/plugin/metricagent/metric_agent.go index 30ce39b30..07f08eb26 100644 --- a/cmd/poller/plugin/metricagent/metric_agent.go +++ b/cmd/poller/plugin/metricagent/metric_agent.go @@ -6,6 +6,7 @@ package metricagent import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/slogx" @@ -25,14 +26,14 @@ func New(p *plugin.AbstractPlugin) *MetricAgent { return &MetricAgent{AbstractPlugin: p} } -func (a *MetricAgent) Init() error { +func (a *MetricAgent) Init(remote conf.Remote) error { var ( err error count int ) - if err := a.AbstractPlugin.Init(); err != nil { + if err := a.AbstractPlugin.Init(remote); err != nil { return err } diff --git a/cmd/poller/plugin/metricagent/metric_agent_test.go b/cmd/poller/plugin/metricagent/metric_agent_test.go index 8d6bd785a..532c8b39c 100644 --- a/cmd/poller/plugin/metricagent/metric_agent_test.go +++ b/cmd/poller/plugin/metricagent/metric_agent_test.go @@ -6,6 +6,7 @@ package metricagent import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" "testing" @@ -33,7 +34,7 @@ func newAgent() *MetricAgent { abc := plugin.New("Test", nil, params, nil, "", nil) p := &MetricAgent{AbstractPlugin: abc} - if err := p.Init(); err != nil { + if err := p.Init(conf.Remote{}); err != nil { panic(err) } return p diff --git a/cmd/poller/plugin/plugin.go b/cmd/poller/plugin/plugin.go index ea69207ae..a0d0924f4 100644 --- a/cmd/poller/plugin/plugin.go +++ b/cmd/poller/plugin/plugin.go @@ -29,6 +29,7 @@ import ( "fmt" "github.com/netapp/harvest/v2/cmd/poller/options" "github.com/netapp/harvest/v2/pkg/auth" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree/node" @@ -44,7 +45,7 @@ const DefaultPollInterval = 3 * time.Minute // Plugin defines the methods of a plugin type Plugin interface { GetName() string - Init() error + Init(conf.Remote) error Run(map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) } @@ -130,7 +131,7 @@ func (p *AbstractPlugin) GetName() string { } // Init initializes the plugin by calling InitAbc -func (p *AbstractPlugin) Init() error { +func (p *AbstractPlugin) Init(conf.Remote) error { return p.InitAbc() } diff --git a/cmd/poller/plugin/test/plugin_test.go b/cmd/poller/plugin/test/plugin_test.go index c17998fcd..26e4a06ee 100644 --- a/cmd/poller/plugin/test/plugin_test.go +++ b/cmd/poller/plugin/test/plugin_test.go @@ -4,6 +4,7 @@ import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" "github.com/netapp/harvest/v2/cmd/poller/plugin/aggregator" "github.com/netapp/harvest/v2/cmd/poller/plugin/labelagent" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/matrix" "github.com/netapp/harvest/v2/pkg/tree" "github.com/netapp/harvest/v2/pkg/tree/node" @@ -12,6 +13,7 @@ import ( func TestMultipleRule(t *testing.T) { var Plugins []plugin.Plugin + remote := conf.Remote{} defaultTemplate, _ := tree.ImportYaml("testdata/sample.yaml") p := defaultTemplate.GetChildS("plugins") @@ -35,7 +37,7 @@ func TestMultipleRule(t *testing.T) { } abc := plugin.New("Test", nil, params, nil, "", nil) lb = &labelagent.LabelAgent{AbstractPlugin: abc} - if err := lb.Init(); err != nil { + if err := lb.Init(remote); err != nil { t.Fatal(err) } Plugins = append(Plugins, lb) @@ -49,7 +51,7 @@ func TestMultipleRule(t *testing.T) { abc := plugin.New("Test", nil, params, nil, "", nil) ag := &aggregator.Aggregator{AbstractPlugin: abc} - if err := ag.Init(); err != nil { + if err := ag.Init(remote); err != nil { t.Fatal(err) } Plugins = append(Plugins, ag) diff --git a/cmd/poller/poller.go b/cmd/poller/poller.go index 7bcdf8f82..7c7a65b6c 100644 --- a/cmd/poller/poller.go +++ b/cmd/poller/poller.go @@ -31,6 +31,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/netapp/harvest/v2/cmd/collectors" _ "github.com/netapp/harvest/v2/cmd/collectors/ems" _ "github.com/netapp/harvest/v2/cmd/collectors/keyperf" _ "github.com/netapp/harvest/v2/cmd/collectors/restperf" @@ -48,7 +49,6 @@ import ( "github.com/netapp/harvest/v2/cmd/poller/plugin" "github.com/netapp/harvest/v2/cmd/poller/schedule" "github.com/netapp/harvest/v2/cmd/tools/rest" - "github.com/netapp/harvest/v2/pkg/api/ontapi/zapi" "github.com/netapp/harvest/v2/pkg/auth" "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" @@ -92,10 +92,6 @@ var ( opts *options.Options ) -const ( - NoUpgrade = "HARVEST_NO_COLLECTOR_UPGRADE" -) - // init with default configuration that logs to the console and harvest.log var logger = slog.Default() @@ -134,6 +130,7 @@ type Poller struct { hasPromExporter bool maxRssBytes uint64 startTime time.Time + remote conf.Remote } // Init starts Poller, reads parameters, opens zeroLog handler, initializes metadata, @@ -304,6 +301,8 @@ func (p *Poller) Init() error { return errs.New(errs.ErrNoCollector, "no collectors") } + p.negotiateONTAPAPI(filteredCollectors) + objectsToCollectors := make(map[string][]objectCollector) for _, c := range filteredCollectors { _, ok := util.IsCollector[c.Name] @@ -424,8 +423,8 @@ func uniquifyObjectCollectors(objectsToCollectors map[string][]objectCollector) specialCaseQtree(objectsToCollectors) - for _, collectors := range objectsToCollectors { - uniqueOCs = append(uniqueOCs, nonOverlappingCollectors(collectors)...) + for _, col := range objectsToCollectors { + uniqueOCs = append(uniqueOCs, nonOverlappingCollectors(col)...) } return uniqueOCs @@ -569,7 +568,6 @@ func (p *Poller) Run() { upe := 0 // up exporters // update status of collectors - var remote conf.Remote for _, c := range p.collectors { code, _, msg := c.GetStatus() @@ -588,13 +586,11 @@ func (p *Poller) Run() { instance.SetLabel("reason", strings.ReplaceAll(msg, "\"", "")) } } - - remote = c.GetRemote() } // add remote version and name to metadata - p.status.GetInstance("remote").SetLabel("version", remote.Version) - p.status.GetInstance("remote").SetLabel("name", remote.Name) + p.status.GetInstance("remote").SetLabel("version", p.remote.Version) + p.status.GetInstance("remote").SetLabel("name", p.remote.Name) // update status of exporters for _, ee := range p.exporters { @@ -640,10 +636,14 @@ func (p *Poller) Run() { if upc != upCollectors || upe != upExporters { logger.Info( "updated status", - slog.Int("upCollectors", upc), - slog.Int("collectorsTotal", len(p.collectors)), - slog.Int("upExporters", upe), - slog.Int("exportersTotal", len(p.exporters)), + slog.Group("collectors", + slog.Int("up", upc), + slog.Int("total", len(p.collectors)), + ), + slog.Group("exporters", + slog.Int("up", upe), + slog.Int("total", len(p.exporters)), + ), ) } upCollectors = upc @@ -711,7 +711,7 @@ func (p *Poller) readObjects(c conf.Collector) ([]objectCollector, error) { template, subTemplate *node.Node ) - c = p.upgradeCollector(c) + c = p.upgradeCollector(c, p.remote) class = c.Name // throw warning for deprecated collectors if r, d := deprecatedCollectors[strings.ToLower(class)]; d { @@ -803,7 +803,7 @@ type objectCollector struct { // dynamically load and initialize a collector func (p *Poller) loadCollectorObject(ocs []objectCollector) error { - var collectors []collector.Collector + var cols []collector.Collector logger.Debug("Starting collectors", slog.Int("collectors", len(ocs))) @@ -833,7 +833,7 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error { logger.Debug("ignoring collector", slog.String("collector", oc.class), slog.String("object", oc.object)) continue } - collectors = append(collectors, col) + cols = append(cols, col) logger.Debug( "initialized collector-object", slog.String("collector", oc.class), @@ -842,9 +842,9 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error { } } - p.collectors = append(p.collectors, collectors...) + p.collectors = append(p.collectors, cols...) // link each collector with requested exporter & update metadata - for _, col := range collectors { + for _, col := range cols { if col == nil { logger.Warn("ignoring nil collector") continue @@ -879,23 +879,24 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error { return nil } -func nonOverlappingCollectors(collectors []objectCollector) []objectCollector { - if len(collectors) == 0 { +func nonOverlappingCollectors(objectCollectors []objectCollector) []objectCollector { + if len(objectCollectors) == 0 { return []objectCollector{} } - if len(collectors) == 1 { - return collectors + if len(objectCollectors) == 1 { + return objectCollectors } unique := make([]objectCollector, 0) - conflicts := map[string]string{ - "Zapi": "Rest", - "ZapiPerf": "RestPerf", - "Rest": "Zapi", - "RestPerf": "ZapiPerf", + conflicts := map[string][]string{ + "Zapi": {"Rest"}, + "ZapiPerf": {"RestPerf", "KeyPerf"}, + "Rest": {"Zapi"}, + "RestPerf": {"ZapiPerf", "KeyPerf"}, + "KeyPerf": {"ZapiPerf", "RestPerf"}, } - for _, c := range collectors { + for _, c := range objectCollectors { conflict, ok := conflicts[c.class] if ok { if collectorContains(unique, conflict, c.class) { @@ -907,12 +908,14 @@ func nonOverlappingCollectors(collectors []objectCollector) []objectCollector { return unique } -func collectorContains(unique []objectCollector, searches ...string) bool { +func collectorContains(unique []objectCollector, conflicts []string, search string) bool { for _, o := range unique { - for _, s := range searches { - if o.class == s { - return true - } + if o.class == search { + return true + } + has := slices.Contains(conflicts, o.class) + if has { + return true } } return false @@ -988,7 +991,7 @@ func (p *Poller) newCollector(class string, object string, template *node.Node) if !ok { return nil, errs.New(errs.ErrNoCollector, "no collectors") } - delegate := collector.New(class, object, p.options, template.Copy(), p.auth) + delegate := collector.New(class, object, p.options, template.Copy(), p.auth, p.remote) err = col.Init(delegate) return col, err } @@ -1328,67 +1331,53 @@ func (p *Poller) createClient() { // upgradeCollector checks if the collector c should be upgraded to a REST collector. // ZAPI collectors should be upgraded to REST collectors when the cluster no longer speaks Zapi -func (p *Poller) upgradeCollector(c conf.Collector) conf.Collector { +func (p *Poller) upgradeCollector(c conf.Collector, remote conf.Remote) conf.Collector { // If REST is desired, use REST // If ZAPI is desired, check that the cluster speaks ZAPI and if so, use ZAPI, otherwise use REST + // If KeyPerf is desired, negotiate the API // EMS and StorageGRID are ignored - if !strings.HasPrefix(c.Name, "Zapi") { + if _, ok := util.IsONTAPCollector[c.Name]; !ok { return c } - return p.negotiateAPI(c, p.doZAPIsExist) -} + isKeyPerf := remote.IsKeyPerf() + replaced := c.Name -// Harvest will upgrade ZAPI conversations to REST in two cases: -// - if ONTAP returns a ZAPI error with errno=61253 -// - if ONTAP returns an HTTP status code of 400 -func (p *Poller) negotiateAPI(c conf.Collector, checkZAPIs func() error) conf.Collector { - var switchToRest bool - err := checkZAPIs() + if strings.HasPrefix(replaced, "Zapi") { - if err != nil { - var he errs.HarvestError - if errors.As(err, &he) { - if he.ErrNum == errs.ErrNumZAPISuspended { - logger.Warn("ZAPIs suspended. Use REST", slog.String("collector", c.Name)) - switchToRest = true + if remote.ZAPIsExist { + switch replaced { + case "Zapi": + return c + case "ZapiPerf": + if isKeyPerf { + replaced = "RestPerf" + } else { + return c + } } + } - if he.StatusCode == http.StatusBadRequest { - logger.Warn("ZAPIs EOA. Use REST", slog.String("collector", c.Name)) - switchToRest = true - } + replaced = strings.ReplaceAll(replaced, "Zapi", "Rest") + if isKeyPerf { + replaced = strings.ReplaceAll(replaced, "RestPerf", "KeyPerf") } - if switchToRest { - upgradeCollector := strings.ReplaceAll(c.Name, "Zapi", "Rest") - return conf.Collector{ - Name: upgradeCollector, - Templates: c.Templates, - } + return conf.Collector{ + Name: replaced, + Templates: c.Templates, } - logger.Error("Failed to negotiateAPI", slogx.Err(err), slog.String("collector", c.Name)) } - return c -} - -func (p *Poller) doZAPIsExist() error { - var ( - poller *conf.Poller - connection *zapi.Client - err error - ) - - // connect to the cluster and retrieve the system version - if poller, err = conf.PollerNamed(opts.Poller); err != nil { - return err + if isKeyPerf { + replaced := strings.ReplaceAll(c.Name, "RestPerf", "KeyPerf") + return conf.Collector{ + Name: replaced, + Templates: c.Templates, + } } - if connection, err = zapi.New(poller, p.auth); err != nil { - return err - } - return connection.Init(2) + return c } // set the poller's confPath using the following precedence: @@ -1460,29 +1449,29 @@ func (p *Poller) sendHarvestVersion() error { if !p.targetIsOntap() { return nil } - // connect to the cluster and retrieve the system version - if poller, err = conf.PollerNamed(opts.Poller); err != nil { - return err - } - timeout, _ := time.ParseDuration(rest.DefaultTimeout) - if connection, err = rest.New(poller, timeout, p.auth); err != nil { - return err - } - err = connection.Init(2) - if err != nil { - return err + if !p.remote.HasREST { + return nil } - // Check if the cluster is running ONTAP 9.11.1 or later - // If it is, send a harvestTag to the cluster to indicate that Harvest is running + // If the cluster is running ONTAP 9.11.1 or later, + // send a harvestTag to the cluster to indicate that Harvest is running. // Otherwise, do nothing - ontapVersion, err := goversion.NewVersion(connection.Remote().Version) + ontapVersion, err := goversion.NewVersion(p.remote.Version) if err != nil { return err } if ontapVersion.LessThan(goversion.Must(goversion.NewVersion("9.11.1"))) { + return nil + } + + // connect to the cluster + if poller, err = conf.PollerNamed(opts.Poller); err != nil { + return err + } + timeout, _ := time.ParseDuration(rest.DefaultTimeout) + if connection, err = rest.New(poller, timeout, p.auth); err != nil { return err } @@ -1502,6 +1491,30 @@ func (p *Poller) sendHarvestVersion() error { return nil } +func (p *Poller) negotiateONTAPAPI(cols []conf.Collector) { + anyONTAP := false + for _, c := range cols { + if _, ok := util.IsONTAPCollector[c.Name]; ok { + anyONTAP = true + break + } + } + + if !anyONTAP { + return + } + + remote, err := collectors.GatherClusterInfo(opts.Poller, p.auth) + if err != nil { + logger.Error("Failed to gather cluster info", slogx.Err(err)) + return + } + + slog.Info("Cluster info", slog.Any("remote", remote)) + + p.remote = remote +} + func startPoller(_ *cobra.Command, _ []string) { poller := &Poller{} poller.options = opts diff --git a/cmd/poller/poller_test.go b/cmd/poller/poller_test.go index 7f3f9a4d0..813168186 100644 --- a/cmd/poller/poller_test.go +++ b/cmd/poller/poller_test.go @@ -1,12 +1,10 @@ package main import ( - "errors" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/tree/node" - "os" "strings" "testing" ) @@ -132,29 +130,35 @@ func TestCollectorUpgrade(t *testing.T) { poller := Poller{params: &conf.Poller{}} type test struct { - name string - clusterVersion string - askFor string - wantCollector string - setEnvVar bool - check func() error + name string + askFor string + wantCollector string + remote conf.Remote } - zapisExist := func() error { return nil } - zapisDoNotExist := func() error { return errors.New("boom") } + ontap911 := conf.Remote{Version: "9.11.1", ZAPIsExist: true} + ontap917 := conf.Remote{Version: "9.17.1", ZAPIsExist: false} + keyPerf := conf.Remote{Version: "9.17.1", ZAPIsExist: false, IsDisaggregated: true} + keyPerfWithZapi := conf.Remote{Version: "9.17.1", ZAPIsExist: true, IsDisaggregated: true} tests := []test{ - {name: "9.11 use ZAPI", clusterVersion: "9.11.1", askFor: "Zapi", wantCollector: "Zapi"}, - {name: "9.11 use REST", clusterVersion: "9.11.1", askFor: "Rest", wantCollector: "Rest"}, - {name: "9.12 upgrade", clusterVersion: "9.12.1", askFor: "Zapi", wantCollector: "Zapi"}, - {name: "9.12 w/ envar", clusterVersion: "9.12.1", askFor: "Zapi", wantCollector: "Zapi", setEnvVar: true}, - {name: "9.12 REST", clusterVersion: "9.12.3", askFor: "Rest", wantCollector: "Rest", setEnvVar: true}, - {name: "9.13 RestPerf", clusterVersion: "9.13.1", askFor: "ZapiPerf", wantCollector: "ZapiPerf"}, - {name: "9.13 REST w/ envar", clusterVersion: "9.13.1", askFor: "Rest", wantCollector: "Rest", setEnvVar: true}, - {name: "9.13 REST w/ envar", clusterVersion: "9.13.1", askFor: "Zapi", wantCollector: "Zapi", setEnvVar: true}, - {name: "9.13 REST w/ envar", clusterVersion: "9.13.1", askFor: "Rest", wantCollector: "Rest", setEnvVar: true, - check: zapisDoNotExist}, - {name: "9.13 REST", clusterVersion: "9.13.1", askFor: "Rest", wantCollector: "Rest"}, + {name: "9.11 w/ ZAPI", remote: ontap911, askFor: "Zapi", wantCollector: "Zapi"}, + {name: "9.11 w/ ZAPI", remote: ontap911, askFor: "ZapiPerf", wantCollector: "ZapiPerf"}, + {name: "9.11 w/ ZAPI", remote: ontap911, askFor: "Rest", wantCollector: "Rest"}, + {name: "9.11 w/ ZAPI", remote: ontap911, askFor: "KeyPerf", wantCollector: "KeyPerf"}, + + {name: "9.17 no ZAPI", remote: ontap917, askFor: "Zapi", wantCollector: "Rest"}, + {name: "9.17 no ZAPI", remote: ontap917, askFor: "ZapiPerf", wantCollector: "RestPerf"}, + {name: "9.17 no ZAPI", remote: ontap917, askFor: "KeyPerf", wantCollector: "KeyPerf"}, + + {name: "KeyPerf", remote: keyPerf, askFor: "Zapi", wantCollector: "Rest"}, + {name: "KeyPerf", remote: keyPerf, askFor: "Rest", wantCollector: "Rest"}, + {name: "KeyPerf", remote: keyPerf, askFor: "ZapiPerf", wantCollector: "KeyPerf"}, + {name: "KeyPerf", remote: keyPerf, askFor: "RestPerf", wantCollector: "KeyPerf"}, + + {name: "KeyPerf w/ ZAPI", remote: keyPerfWithZapi, askFor: "Zapi", wantCollector: "Zapi"}, + {name: "KeyPerf w/ ZAPI", remote: keyPerfWithZapi, askFor: "ZapiPerf", wantCollector: "KeyPerf"}, + {name: "KeyPerf w/ ZAPI", remote: keyPerfWithZapi, askFor: "RestPerf", wantCollector: "KeyPerf"}, } for _, tt := range tests { @@ -162,15 +166,8 @@ func TestCollectorUpgrade(t *testing.T) { collector := conf.Collector{ Name: tt.askFor, } - if tt.setEnvVar { - _ = os.Setenv(NoUpgrade, "1") - } else { - _ = os.Unsetenv(NoUpgrade) - } - if tt.check == nil { - tt.check = zapisExist - } - newCollector := poller.negotiateAPI(collector, tt.check) + + newCollector := poller.upgradeCollector(collector, tt.remote) if newCollector.Name != tt.wantCollector { t.Errorf("got = [%s] want [%s]", newCollector.Name, tt.wantCollector) } @@ -193,6 +190,9 @@ func Test_nonOverlappingCollectors(t *testing.T) { args: ocs("Zapi", "Rest", "Rest", "Rest", "Rest", "Rest", "Zapi", "Zapi", "Zapi", "Zapi", "Zapi"), want: ocs("Zapi")}, {name: "non ontap", args: ocs("Rest", "SG"), want: ocs("Rest", "SG")}, + {name: "no overlap", args: ocs("Rest", "KeyPerf"), want: ocs("Rest", "KeyPerf")}, + {name: "overlap", args: ocs("RestPerf", "KeyPerf"), want: ocs("RestPerf")}, + {name: "overlap", args: ocs("KeyPerf", "KeyPerf"), want: ocs("KeyPerf")}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -227,6 +227,12 @@ func Test_uniquifyObjectCollectors(t *testing.T) { want: []objectCollector{{class: "Rest", object: "Qtree"}, {class: "Rest", object: "Quota"}}}, {name: "qtree-zapi-disable-quota", args: objectCollectorMap("Qtree: Zapi, Rest", "Quota: Rest"), want: []objectCollector{{class: "Zapi", object: "Qtree"}}}, + {name: "volume-restperf", args: objectCollectorMap("Volume: RestPerf, KeyPerf"), + want: []objectCollector{{class: "RestPerf", object: "Volume"}}}, + {name: "volume-keyperf", args: objectCollectorMap("Volume: KeyPerf, RestPerf"), + want: []objectCollector{{class: "KeyPerf", object: "Volume"}}}, + {name: "multi-keyperf", args: objectCollectorMap("Volume: RestPerf", "Aggregate: KeyPerf"), + want: []objectCollector{{class: "RestPerf", object: "Volume"}, {class: "KeyPerf", object: "Aggregate"}}}, } for _, tt := range tests { diff --git a/cmd/tools/generate/generate.go b/cmd/tools/generate/generate.go index 128b32f96..daa9209b4 100644 --- a/cmd/tools/generate/generate.go +++ b/cmd/tools/generate/generate.go @@ -583,7 +583,7 @@ func BuildMetrics(dir, configPath, pollerName string) (map[string]Counter, conf. fmt.Printf("error creating new client %+v\n", err) os.Exit(1) } - if err = restClient.Init(2); err != nil { + if err = restClient.Init(2, conf.Remote{}); err != nil { fmt.Printf("error init rest client %+v\n", err) os.Exit(1) } diff --git a/cmd/tools/rest/client.go b/cmd/tools/rest/client.go index 678d4a9b7..e520640a1 100644 --- a/cmd/tools/rest/client.go +++ b/cmd/tools/rest/client.go @@ -344,18 +344,31 @@ func (c *Client) UpdateClusterInfo(retries int) error { } results := gjson.ParseBytes(content) + c.remote.Model = "cdot" c.remote.Name = results.Get("name").String() c.remote.UUID = results.Get("uuid").String() - c.remote.Version = - results.Get("version.generation").String() + "." + - results.Get("version.major").String() + "." + - results.Get("version.minor").String() + c.remote.Version = results.Get("version.generation").String() + "." + + results.Get("version.major").String() + "." + + results.Get("version.minor").String() + c.remote.Release = results.Get("version.full").String() + c.remote.IsSanOptimized = results.Get("san_optimized").Bool() + c.remote.IsDisaggregated = results.Get("disaggregated").Bool() + c.remote.IsClustered = true + c.remote.HasREST = true + return nil } + return err } -func (c *Client) Init(retries int) error { +func (c *Client) Init(retries int, remote conf.Remote) error { + c.remote = remote + + if !remote.IsZero() { + return nil + } + return c.UpdateClusterInfo(retries) } diff --git a/cmd/tools/rest/rest.go b/cmd/tools/rest/rest.go index 7b5d958c2..ff347ae06 100644 --- a/cmd/tools/rest/rest.go +++ b/cmd/tools/rest/rest.go @@ -173,7 +173,7 @@ func fetchData(poller *conf.Poller, timeout time.Duration) (*Results, error) { } // Init is called to get the cluster version - err = client.Init(1) + err = client.Init(1, conf.Remote{}) if err != nil { var re *errs.RestError if errors.As(err, &re) { diff --git a/cmd/tools/template/template.go b/cmd/tools/template/template.go index 93982ff5b..11ccd5f11 100644 --- a/cmd/tools/template/template.go +++ b/cmd/tools/template/template.go @@ -9,6 +9,7 @@ import ( "github.com/netapp/harvest/v2/cmd/poller/plugin/labelagent" max2 "github.com/netapp/harvest/v2/cmd/poller/plugin/max" "github.com/netapp/harvest/v2/cmd/poller/plugin/metricagent" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/errs" "github.com/netapp/harvest/v2/pkg/tree" "github.com/netapp/harvest/v2/pkg/tree/node" @@ -291,7 +292,7 @@ func readMax(template *node.Node, model *Model) error { if len(children) != 0 { abc := plugin.AbstractPlugin{Params: children[0]} mm := max2.New(&abc) - err := mm.Init() + err := mm.Init(conf.Remote{}) if err != nil { return err } @@ -308,7 +309,7 @@ func readMetricAgent(template *node.Node, model *Model) error { } abc := plugin.AbstractPlugin{Params: children[0]} ma := metricagent.New(&abc) - err := ma.Init() + err := ma.Init(conf.Remote{}) if err != nil { return err } @@ -321,7 +322,7 @@ func readAggregator(template *node.Node, model *Model) error { if len(children) != 0 { abc := plugin.AbstractPlugin{Params: children[0]} agg := aggregator.New(&abc) - err := agg.Init() + err := agg.Init(conf.Remote{}) if err != nil { return err } @@ -339,7 +340,7 @@ func readLabelAgent(template *node.Node, model *Model) error { } abc := plugin.AbstractPlugin{Params: children[0]} la := labelagent.New(&abc) - err := la.Init() + err := la.Init(conf.Remote{}) if err != nil { return err } diff --git a/cmd/tools/zapi/zapi.go b/cmd/tools/zapi/zapi.go index 23aacd311..5363e68e4 100644 --- a/cmd/tools/zapi/zapi.go +++ b/cmd/tools/zapi/zapi.go @@ -143,7 +143,7 @@ func doCmd(cmd string) { log.Fatal(err) } - if err = connection.Init(2); err != nil { + if err = connection.Init(2, conf.Remote{}); err != nil { log.Fatal(err) } diff --git a/integration/test/counter_test.go b/integration/test/counter_test.go index 311f12955..b415ac323 100644 --- a/integration/test/counter_test.go +++ b/integration/test/counter_test.go @@ -70,7 +70,7 @@ func TestCounters(t *testing.T) { os.Exit(1) } - if err = client.Init(5); err != nil { + if err = client.Init(5, conf.Remote{}); err != nil { slog.Error("client init failed", slogx.Err(err)) os.Exit(1) } diff --git a/pkg/api/ontapi/zapi/client.go b/pkg/api/ontapi/zapi/client.go index e1876e897..c9cbcab33 100644 --- a/pkg/api/ontapi/zapi/client.go +++ b/pkg/api/ontapi/zapi/client.go @@ -32,13 +32,13 @@ type Client struct { client *http.Client request *http.Request buffer *bytes.Buffer - system *system apiVersion string vfiler string Logger *slog.Logger logZapi bool // used to log ZAPI request/response auth *auth.Credentials Metadata *util.Metadata + remote conf.Remote } type Response struct { @@ -144,8 +144,15 @@ func parseClientTimeout(clientTimeout string) (time.Duration, error) { // Init connects to the cluster and retrieves system info // it will give up after retries -func (c *Client) Init(retries int) error { +func (c *Client) Init(retries int, remote conf.Remote) error { var err error + + c.remote = remote + + if !remote.IsZero() { + return nil + } + for range retries { if err = c.getSystem(); err == nil { break @@ -156,32 +163,32 @@ func (c *Client) Init(retries int) error { // Name returns the name of the Cluster func (c *Client) Name() string { - return c.system.name + return c.remote.Name } // IsClustered returns true if ONTAP is clustered or false if it's a 7-mode system func (c *Client) IsClustered() bool { - return c.system.clustered + return c.remote.IsClustered } // Version returns version of the ONTAP server (generation, major and minor) -func (c *Client) Version() [3]int { - return c.system.version +func (c *Client) Version() string { + return c.remote.Version } // Release returns string with long release info of the ONTAP system func (c *Client) Release() string { - return c.system.release + return c.remote.Release } // Serial returns the serial number of the ONTAP system func (c *Client) Serial() string { - return c.system.serial + return c.remote.Serial } // ClusterUUID returns the cluster UUID of a c-mode system and system-id for 7-mode func (c *Client) ClusterUUID() string { - return c.system.clusterUUID + return c.remote.UUID } // Info returns a string with details about the ONTAP system identity @@ -192,7 +199,7 @@ func (c *Client) Info() string { } else { model = "7MODE" } - version = fmt.Sprintf("(%s version %d.%d.%d)", model, c.system.version[0], c.system.version[1], c.system.version[2]) + version = fmt.Sprintf("(%s version %s)", model, c.remote.Version) return fmt.Sprintf("%s %s (serial %s) (%s)", c.Name(), version, c.Serial(), c.Release()) } @@ -579,10 +586,14 @@ func (c *Client) SetTimeout(timeout string) { c.client.Timeout = newTimeout } +func (c *Client) Remote() conf.Remote { + return c.remote +} + // NewTestClient It's used for unit test only func NewTestClient() *Client { return &Client{ - system: &system{name: "testCluster", clustered: true}, + remote: conf.Remote{Name: "testCluster", IsClustered: true}, request: &http.Request{}, Metadata: &util.Metadata{}, } diff --git a/pkg/api/ontapi/zapi/system.go b/pkg/api/ontapi/zapi/system.go index aada83593..7ea0f59b0 100644 --- a/pkg/api/ontapi/zapi/system.go +++ b/pkg/api/ontapi/zapi/system.go @@ -4,112 +4,99 @@ package zapi import ( "errors" "fmt" + "github.com/netapp/harvest/v2/pkg/conf" "github.com/netapp/harvest/v2/pkg/tree/node" "regexp" "strconv" ) -type system struct { - name string - serial string - clusterUUID string - release string - version [3]int - clustered bool -} - // See system_test.go for examples -func (s *system) parse7mode(release string) error { +func parse7mode(release string) (int, int, int, error) { // NetApp Release 8.2P4 7-Mode: Tue Oct 1 11:24:04 PDT 2013 r := regexp.MustCompile(`NetApp Release (\d+)\.(\d+)\w(\d+)`) matches := r.FindStringSubmatch(release) if len(matches) == 4 { - setInt(&s.version[0], matches[1]) - setInt(&s.version[1], matches[2]) - setInt(&s.version[2], matches[3]) - return nil + return toInt(matches[1]), toInt(matches[2]), toInt(matches[3]), nil } r = regexp.MustCompile(`NetApp Release (\d+)\.(\d+)\.(\d+)`) matches = r.FindStringSubmatch(release) if len(matches) == 4 { - setInt(&s.version[0], matches[1]) - setInt(&s.version[1], matches[2]) - setInt(&s.version[2], matches[3]) - return nil + return toInt(matches[1]), toInt(matches[2]), toInt(matches[3]), nil } r = regexp.MustCompile(`NetApp Release (\d+)\.(\d+)\.(\d+)\.(\d+)`) matches = r.FindStringSubmatch(release) if len(matches) == 5 { // 7.0.0.1 becomes 7.0.0 - setInt(&s.version[0], matches[1]) - setInt(&s.version[1], matches[2]) - setInt(&s.version[2], matches[3]) - return nil + return toInt(matches[1]), toInt(matches[2]), toInt(matches[3]), nil } - return fmt.Errorf("no valid version tuple found for=[%s]", release) + return 0, 0, 0, fmt.Errorf("no valid version tuple found for=[%s]", release) } -func setInt(i *int, s string) { +func toInt(s string) int { value, err := strconv.Atoi(s) if err != nil { - return + return 0 } - *i = value + return value } // getSystem connects to ONTAP system and retrieves its identity and version // this works for Clustered and 7-mode systems func (c *Client) getSystem() error { var ( - s system - response *node.Node - err error + r conf.Remote + release string + isClustered bool + versionT [3]int + response *node.Node + err error ) - s = system{} + r = conf.Remote{} // fetch system version and model if response, err = c.InvokeRequestString("system-get-version"); err != nil { return err } - s.release = response.GetChildContentS("version") + release = response.GetChildContentS("version") if version := response.GetChildS("version-tuple"); version != nil { if tuple := version.GetChildS("system-version-tuple"); tuple != nil { for i, v := range []string{"generation", "major", "minor"} { if n, err := strconv.ParseInt(tuple.GetChildContentS(v), 0, 16); err == nil { - s.version[i] = int(n) + versionT[i] = int(n) } } } } - // if version tuple is missing try to parse from the release string + // if version tuple is missing, try to parse from the release string, // this is usually the case with 7mode systems - // e.g. NetApp Release 8.2P4 7-Mode: Tue Oct 1 11:24:04 PDT 2013 - if s.version[0] == 0 { - err := s.parse7mode(s.release) + // e.g., NetApp Release 8.2P4 7-Mode: Tue Oct 1 11:24:04 PDT 2013 + if versionT[0] == 0 { + i0, i1, i2, err := parse7mode(release) if err != nil { return err } + versionT[0] = i0 + versionT[1] = i1 + versionT[2] = i2 } - if clustered := response.GetChildContentS("is-clustered"); clustered == "" { + clustered := response.GetChildContentS("is-clustered") + if clustered == "" { return errors.New("missing attribute [is-clustered]") - } else if clustered == "true" { - s.clustered = true - } else { - s.clustered = false } + isClustered = clustered == "true" // fetch system name and serial number request := "cluster-identity-get" - if !s.clustered { + if !isClustered { request = "system-get-info" } @@ -117,21 +104,32 @@ func (c *Client) getSystem() error { return err } - if s.clustered { + if isClustered { if attrs := response.GetChildS("attributes"); attrs != nil { if info := attrs.GetChildS("cluster-identity-info"); info != nil { - s.name = info.GetChildContentS("cluster-name") - s.clusterUUID = info.GetChildContentS("cluster-uuid") + r.Name = info.GetChildContentS("cluster-name") + r.UUID = info.GetChildContentS("cluster-uuid") } } } else { if info := response.GetChildS("system-info"); info != nil { - s.name = info.GetChildContentS("system-name") - s.serial = info.GetChildContentS("system-serial-number") - // There is no uuid for non cluster mode, using system-id. - s.clusterUUID = info.GetChildContentS("system-id") + r.Name = info.GetChildContentS("system-name") + r.Serial = info.GetChildContentS("system-serial-number") + // There is no uuid for non-cluster mode, using system-id. + r.UUID = info.GetChildContentS("system-id") } } - c.system = &s + + r.Version = strconv.Itoa(versionT[0]) + "." + strconv.Itoa(versionT[1]) + "." + strconv.Itoa(versionT[2]) + if isClustered { + r.Model = "cdot" + } else { + r.Model = "7mode" + } + r.IsClustered = isClustered + r.ZAPIsExist = true + r.Release = release + c.remote = r + return nil } diff --git a/pkg/api/ontapi/zapi/system_test.go b/pkg/api/ontapi/zapi/system_test.go index 50d4d80c8..ba167b378 100644 --- a/pkg/api/ontapi/zapi/system_test.go +++ b/pkg/api/ontapi/zapi/system_test.go @@ -1,6 +1,7 @@ package zapi import ( + "fmt" "testing" ) @@ -8,22 +9,21 @@ func Test_7modeParsing(t *testing.T) { type test struct { name string release string - want system + want string wantErr bool } tests := []test{ - {name: "issue-376", release: "NetApp Release 8.2P4 7-Mode: Tue Oct 1 11:24:04 PDT 2013", want: system{version: [3]int{8, 2, 4}}}, - {name: "7.0.1", release: "NetApp Release 7.0.0.1: Wed Mar 2 22:20:44 PST 2005", want: system{version: [3]int{7, 0, 0}}}, - {name: "7.0.4", release: "NetApp Release 7.0.4: Sun Feb 5 00:52:53 PST 2006", want: system{version: [3]int{7, 0, 4}}}, - {name: "6.4.1", release: "NetApp Release 6.4R1: Thu Mar 13 23:56:30 PST 2003", want: system{version: [3]int{6, 4, 1}}}, - {name: "7.3.1", release: "NetApp Release 7.3.1: Thu Jan 8 01:31:42 PST 2009 ", want: system{version: [3]int{7, 3, 1}}}, + {name: "issue-376", release: "NetApp Release 8.2P4 7-Mode: Tue Oct 1 11:24:04 PDT 2013", want: "8.2.4"}, + {name: "7.0.1", release: "NetApp Release 7.0.0.1: Wed Mar 2 22:20:44 PST 2005", want: "7.0.0"}, + {name: "7.0.4", release: "NetApp Release 7.0.4: Sun Feb 5 00:52:53 PST 2006", want: "7.0.4"}, + {name: "6.4.1", release: "NetApp Release 6.4R1: Thu Mar 13 23:56:30 PST 2003", want: "6.4.1"}, + {name: "7.3.1", release: "NetApp Release 7.3.1: Thu Jan 8 01:31:42 PST 2009 ", want: "7.3.1"}, {name: "fail", release: "cromulent house", wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := system{} - err := s.parse7mode(tt.release) + v0, v1, v2, err := parse7mode(tt.release) if err != nil { if tt.wantErr { return @@ -31,11 +31,9 @@ func Test_7modeParsing(t *testing.T) { t.Errorf("got error=%v, want %v", err, tt.want) } - if s.version[0] == 0 { - t.Errorf("got zero version=%v, want %v", s.version, tt.want.version) - } - if s.version[0] != tt.want.version[0] || s.version[1] != tt.want.version[1] || s.version[2] != tt.want.version[2] { - t.Errorf("got version=%v, want %v", s.version, tt.want.version) + got := fmt.Sprintf("%d.%d.%d", v0, v1, v2) + if got != tt.want { + t.Errorf("got version=%v, want %v", got, tt.want) } }) } diff --git a/pkg/conf/remotes.go b/pkg/conf/remotes.go index eac95f8a1..bc961631b 100644 --- a/pkg/conf/remotes.go +++ b/pkg/conf/remotes.go @@ -1,8 +1,23 @@ package conf type Remote struct { - Name string - Model string - UUID string - Version string + Name string + Model string + UUID string + Version string + Release string + Serial string + IsSanOptimized bool + IsDisaggregated bool + ZAPIsExist bool + HasREST bool + IsClustered bool +} + +func (r Remote) IsZero() bool { + return r.Name == "" && r.Model == "" && r.UUID == "" +} + +func (r Remote) IsKeyPerf() bool { + return r.IsDisaggregated && !r.IsSanOptimized } diff --git a/pkg/errs/errors.go b/pkg/errs/errors.go index b9b8f4c49..a38b600b5 100644 --- a/pkg/errs/errors.go +++ b/pkg/errs/errors.go @@ -26,7 +26,6 @@ const ( ErrNoCollector = harvestError("no collectors") ErrNoInstance = harvestError("no instances") ErrNoMetric = harvestError("no metrics") - ErrPanic = harvestError("goroutine panic") ErrPermissionDenied = harvestError("Permission denied") ErrResponseNotFound = harvestError("response not found") ErrWrongTemplate = harvestError("wrong template")