Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: merge compliance and security dashboard + added ARW fields #2207

Merged
merged 10 commits into from
Aug 3, 2023
88 changes: 87 additions & 1 deletion cmd/collectors/rest/plugins/volume/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,21 @@ import (
"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"
"github.com/tidwall/gjson"
"strconv"
"strings"
"time"
)

const HoursInMonth = 24 * 30

type Volume struct {
*plugin.AbstractPlugin
currentVal int
client *rest.Client
aggrsMap map[string]string // aggregate-uuid -> aggregate-name map
arw *matrix.Matrix
}

func New(p *plugin.AbstractPlugin) plugin.Plugin {
Expand Down Expand Up @@ -55,6 +59,16 @@ func (my *Volume) Init() error {
return err
}

my.arw = matrix.New(my.Parent+".Volume", "volume_arw", "volume_arw")
exportOptions := node.NewS("export_options")
instanceKeys := exportOptions.NewChildS("instance_keys", "")
instanceKeys.NewChildS("", "ArwStatus")
my.arw.SetExportOptions(exportOptions)
_, err = my.arw.NewMetricFloat64("status", "status")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid to ignore error here since the matrix was created a few lines above

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

Expand All @@ -79,8 +93,11 @@ func (my *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro
// update volume instance labels
my.updateVolumeLabels(data)

// parse anti_ransomware_start_time, antiRansomwareState for all volumes and export at cluster level
my.handleARWProtection(data)

my.currentVal++
return nil, nil
return []*matrix.Matrix{my.arw}, nil
}

func (my *Volume) updateVolumeLabels(data *matrix.Matrix) {
Expand All @@ -96,6 +113,75 @@ func (my *Volume) updateVolumeLabels(data *matrix.Matrix) {
}
}

func (my *Volume) handleARWProtection(data *matrix.Matrix) {
var (
arwInstance *matrix.Instance
arwStartTimeValue time.Time
err error
)

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

// Set all global labels
my.arw.SetGlobalLabels(data.GetGlobalLabels())
arwStatusValue := "Active Mode"
// Case where cluster don't have any volumes, arwStatus show as 'Not Monitoring'
if len(data.GetInstances()) == 0 {
arwStatusValue = "Not Monitoring"
}

// This is how cluster level arwStatusValue has been calculated based on each volume
// If any one volume arwStatus is disabled --> "Not Monitoring"
// If any one volume has been completed learning mode --> "Switch to Active Mode"
// If all volumes are in learning mode --> "Learning Mode"
// Else indicates arwStatus for all volumes are enabled --> "Active Mode"
for _, volume := range data.GetInstances() {
if arwState := volume.GetLabel("antiRansomwareState"); arwState == "" {
// Case where REST call don't return `antiRansomwareState` field, arwStatus show as 'Not Monitoring'
arwStatusValue = "Not Monitoring"
break
} else {
if arwState == "disabled" {
arwStatusValue = "Not Monitoring"
break
} else if arwState == "dry_run" || arwState == "enable_paused" {
arwStartTime := volume.GetLabel("anti_ransomware_start_time")
if arwStartTime == "" || arwStatusValue == "Switch to Active Mode" {
continue
}
// If ARW startTime is more than 30 days old, which indicates that learning mode has been finished.
if arwStartTimeValue, err = time.Parse(time.RFC3339, arwStartTime); err != nil {
my.Logger.Error().Err(err).Msg("Failed to parse arw start time")
arwStartTimeValue = time.Now()
}
if time.Since(arwStartTimeValue).Hours() > HoursInMonth {
arwStatusValue = "Switch to Active Mode"
} else {
arwStatusValue = "Learning Mode"
}
}
}
}

arwInstanceKey := data.GetGlobalLabels().Get("cluster") + data.GetGlobalLabels().Get("datacenter")
if arwInstance, err = my.arw.NewInstance(arwInstanceKey); err != nil {
my.Logger.Error().Err(err).Str("arwInstanceKey", arwInstanceKey).Msg("Failed to create arw instance")
return
}

arwInstance.SetLabel("ArwStatus", arwStatusValue)
m := my.arw.GetMetric("status")
// populate numeric data
value := 1.0
if err = m.SetValueFloat64(arwInstance, value); err != nil {
my.Logger.Error().Stack().Err(err).Float64("value", value).Msg("Failed to parse value")
} else {
my.Logger.Debug().Float64("value", value).Msg("added value")
}
}

func (my *Volume) getEncryptedDisks() ([]gjson.Result, error) {
var (
result []gjson.Result
Expand Down
25 changes: 25 additions & 0 deletions conf/rest/9.12.0/ems_destination.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

name: EmsDestination
query: api/support/ems/destinations
object: ems_destination

counters:
- ^^destination => destination
- ^^name => name
- ^^type => type
- ^certificate.ca => certificate
- ^filter => filter
- ^syslog => syslog
- ^system_defined => system_defined
- filter:
- system_defined=false

export_options:
instance_keys:
- destination
- name
- type
instance_labels:
- certificate
- filter
- syslog
13 changes: 13 additions & 0 deletions conf/rest/9.12.0/support_auto_update.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

name: SupportAutoUpdate
query: api/support/auto-update
object: support_auto_update

counters:
- ^enabled => auto_update_enabled

export_options:
instance_keys:
- auto_update_enabled
instance_labels:
- auto_update_enabled
4 changes: 4 additions & 0 deletions conf/rest/9.12.0/volume.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ counters:
- ^^svm.name => svm
- ^aggregates.#.name => aggr
- ^aggregates.#.uuid => aggrUuid # handled in plugin for flexgroup
- ^anti_ransomware.dry_run_start_time => anti_ransomware_start_time
- ^anti_ransomware.state => antiRansomwareState
- ^encryption.enabled => isEncrypted
- ^is_svm_root => svm_root
- ^snaplock.type => snaplock_type
- ^snapshot_policy.name => snapshot_policy
- ^space.snapshot.autodelete.enabled => snapshot_autodelete
- ^state => state
- ^style => style
- ^type => type
Expand Down Expand Up @@ -43,6 +45,7 @@ counters:
- space.snapshot.used => snapshots_size_used
- space.used => size_used
- hidden_fields:
- anti_ransomware.dry_run_start_time
- anti_ransomware.state
- autosize
- encryption.enabled
Expand Down Expand Up @@ -137,6 +140,7 @@ export_options:
- is_sis_volume
- root_volume
- snaplock_type
- snapshot_autodelete
- snapshot_policy
- state
- svm_root
Expand Down
2 changes: 2 additions & 0 deletions conf/rest/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ objects:
CloudTarget: cloud_target.yaml
ClusterPeer: clusterpeer.yaml
Disk: disk.yaml
EmsDestination: ems_destination.yaml
# ExportRule: exports.yaml
LIF: lif.yaml
Health: health.yaml
Expand Down Expand Up @@ -42,6 +43,7 @@ objects:
Status: status.yaml
Subsystem: subsystem.yaml
Support: support.yaml
SupportAutoUpdate: support_auto_update.yaml
SVM: svm.yaml
Volume: volume.yaml
VolumeAnalytics: volume_analytics.yaml
27 changes: 27 additions & 0 deletions conf/zapi/cdot/9.8.0/ems_destination.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: EmsDestination
query: ems-event-notification-destination-get-iter
object: ems_destination

counters:
event-notification-destination-info:
- ^^certificate-authority => certificate
- ^^name => name
- ^^type => type
- destination:
- ^^string => destination

collect_only_labels: true

plugins:
- LabelAgent:
exclude_equals:
- destination ``

export_options:
instance_keys:
- destination
- name
- type
instance_labels:
- certificate

3 changes: 3 additions & 0 deletions conf/zapi/cdot/9.8.0/volume.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ counters:
- ^auto-snapshots-enabled => auto_snapshots_enabled
- ^snapshot-policy
- snapshot-count
- volume-snapshot-autodelete-attributes:
- ^is-autodelete-enabled => snapshot_autodelete
- volume-space-attributes:
- expected-available
- filesystem-size => filesystem_size
Expand Down Expand Up @@ -117,6 +119,7 @@ export_options:
- is_sis_volume
- node_root
- root_volume
- snapshot_autodelete
- snapshot_policy
- state
- svm_root
Expand Down
1 change: 1 addition & 0 deletions conf/zapi/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ objects:
CIFSSession: cifs_session.yaml
ClusterPeer: clusterpeer.yaml
Disk: disk.yaml
EmsDestination: ems_destination.yaml
LIF: lif.yaml
Lun: lun.yaml
# NetPort: netPort.yaml
Expand Down
Loading