diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-26 08:15:20 +0000 |
commit | 87d772a7d708fec12f48cd8adc0dedff6e1025da (patch) | |
tree | 1fee344c64cc3f43074a01981e21126c8482a522 /src/go/collectors/go.d.plugin/modules/zfspool | |
parent | Adding upstream version 1.46.3. (diff) | |
download | netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.tar.xz netdata-87d772a7d708fec12f48cd8adc0dedff6e1025da.zip |
Adding upstream version 1.47.0.upstream/1.47.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/zfspool')
13 files changed, 0 insertions, 1095 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/README.md b/src/go/collectors/go.d.plugin/modules/zfspool/README.md deleted file mode 120000 index 8a292336d..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/README.md +++ /dev/null @@ -1 +0,0 @@ -integrations/zfs_pools.md
\ No newline at end of file diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/charts.go b/src/go/collectors/go.d.plugin/modules/zfspool/charts.go deleted file mode 100644 index 45943c656..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/charts.go +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - "fmt" - "strings" - - "github.com/netdata/netdata/go/go.d.plugin/agent/module" -) - -const ( - prioZpoolSpaceUtilization = 2820 + iota - prioZpoolSpaceUsage - prioZpoolFragmentation - prioZpoolHealthState -) - -var zpoolChartsTmpl = module.Charts{ - zpoolSpaceUtilizationChartTmpl.Copy(), - zpoolSpaceUsageChartTmpl.Copy(), - - zpoolFragmentationChartTmpl.Copy(), - - zpoolHealthStateChartTmpl.Copy(), -} - -var ( - zpoolSpaceUtilizationChartTmpl = module.Chart{ - ID: "zfspool_%s_space_utilization", - Title: "Zpool space utilization", - Units: "percentage", - Fam: "space usage", - Ctx: "zfspool.pool_space_utilization", - Type: module.Area, - Priority: prioZpoolSpaceUtilization, - Dims: module.Dims{ - {ID: "zpool_%s_cap", Name: "utilization"}, - }, - } - zpoolSpaceUsageChartTmpl = module.Chart{ - ID: "zfspool_%s_space_usage", - Title: "Zpool space usage", - Units: "bytes", - Fam: "space usage", - Ctx: "zfspool.pool_space_usage", - Type: module.Stacked, - Priority: prioZpoolSpaceUsage, - Dims: module.Dims{ - {ID: "zpool_%s_free", Name: "free"}, - {ID: "zpool_%s_alloc", Name: "used"}, - }, - } - - zpoolFragmentationChartTmpl = module.Chart{ - ID: "zfspool_%s_fragmentation", - Title: "Zpool fragmentation", - Units: "percentage", - Fam: "fragmentation", - Ctx: "zfspool.pool_fragmentation", - Type: module.Line, - Priority: prioZpoolFragmentation, - Dims: module.Dims{ - {ID: "zpool_%s_frag", Name: "fragmentation"}, - }, - } - - zpoolHealthStateChartTmpl = module.Chart{ - ID: "zfspool_%s_health_state", - Title: "Zpool health state", - Units: "state", - Fam: "health", - Ctx: "zfspool.pool_health_state", - Type: module.Line, - Priority: prioZpoolHealthState, - Dims: module.Dims{ - {ID: "zpool_%s_health_state_online", Name: "online"}, - {ID: "zpool_%s_health_state_degraded", Name: "degraded"}, - {ID: "zpool_%s_health_state_faulted", Name: "faulted"}, - {ID: "zpool_%s_health_state_offline", Name: "offline"}, - {ID: "zpool_%s_health_state_unavail", Name: "unavail"}, - {ID: "zpool_%s_health_state_removed", Name: "removed"}, - {ID: "zpool_%s_health_state_suspended", Name: "suspended"}, - }, - } -) - -func (z *ZFSPool) addZpoolCharts(name string) { - charts := zpoolChartsTmpl.Copy() - - for _, chart := range *charts { - chart.ID = fmt.Sprintf(chart.ID, name) - chart.Labels = []module.Label{ - {Key: "pool", Value: name}, - } - for _, dim := range chart.Dims { - dim.ID = fmt.Sprintf(dim.ID, name) - } - } - - if err := z.Charts().Add(*charts...); err != nil { - z.Warning(err) - } -} - -func (z *ZFSPool) removeZpoolCharts(name string) { - px := fmt.Sprintf("zpool_%s_", name) - - for _, chart := range *z.Charts() { - if strings.HasPrefix(chart.ID, px) { - chart.MarkRemove() - chart.MarkNotCreated() - } - } -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/collect.go b/src/go/collectors/go.d.plugin/modules/zfspool/collect.go deleted file mode 100644 index 43994bfc1..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/collect.go +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - "bufio" - "bytes" - "fmt" - "strconv" - "strings" -) - -var zpoolHealthStates = []string{ - "online", - "degraded", - "faulted", - "offline", - "removed", - "unavail", - "suspended", -} - -type zpoolStats struct { - name string - sizeBytes string - allocBytes string - freeBytes string - fragPerc string - capPerc string - dedupRatio string - health string -} - -func (z *ZFSPool) collect() (map[string]int64, error) { - bs, err := z.exec.list() - if err != nil { - return nil, err - } - - zpools, err := parseZpoolListOutput(bs) - if err != nil { - return nil, err - } - - mx := make(map[string]int64) - - z.collectZpoolListStats(mx, zpools) - - return mx, nil -} - -func (z *ZFSPool) collectZpoolListStats(mx map[string]int64, zpools []zpoolStats) { - seen := make(map[string]bool) - - for _, zpool := range zpools { - seen[zpool.name] = true - - if !z.zpools[zpool.name] { - z.addZpoolCharts(zpool.name) - z.zpools[zpool.name] = true - } - - px := "zpool_" + zpool.name + "_" - - if v, ok := parseInt(zpool.sizeBytes); ok { - mx[px+"size"] = v - } - if v, ok := parseInt(zpool.freeBytes); ok { - mx[px+"free"] = v - } - if v, ok := parseInt(zpool.allocBytes); ok { - mx[px+"alloc"] = v - } - if v, ok := parseFloat(zpool.capPerc); ok { - mx[px+"cap"] = int64(v) - } - if v, ok := parseFloat(zpool.fragPerc); ok { - mx[px+"frag"] = int64(v) - } - for _, s := range zpoolHealthStates { - mx[px+"health_state_"+s] = 0 - } - mx[px+"health_state_"+zpool.health] = 1 - } - - for name := range z.zpools { - if !seen[name] { - z.removeZpoolCharts(name) - delete(z.zpools, name) - } - } -} - -func parseZpoolListOutput(bs []byte) ([]zpoolStats, error) { - var lines []string - sc := bufio.NewScanner(bytes.NewReader(bs)) - for sc.Scan() { - if text := strings.TrimSpace(sc.Text()); text != "" { - lines = append(lines, text) - } - - } - if len(lines) < 2 { - return nil, fmt.Errorf("unexpected data: wanted >= 2 lines, got %d", len(lines)) - } - - headers := strings.Fields(lines[0]) - if len(headers) == 0 { - return nil, fmt.Errorf("unexpected data: missing headers") - } - - var zpools []zpoolStats - - /* - # zpool list -p - NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT - rpool 21367462298 9051643576 12240656794 - 33 42 1.00 ONLINE - - zion - - - - - - - FAULTED - - */ - - for _, line := range lines[1:] { - values := strings.Fields(line) - if len(values) != len(headers) { - return nil, fmt.Errorf("unequal columns: headers(%d) != values(%d)", len(headers), len(values)) - } - - var zpool zpoolStats - - for i, v := range values { - v = strings.TrimSpace(v) - switch strings.ToLower(headers[i]) { - case "name": - zpool.name = v - case "size": - zpool.sizeBytes = v - case "alloc": - zpool.allocBytes = v - case "free": - zpool.freeBytes = v - case "frag": - zpool.fragPerc = v - case "cap": - zpool.capPerc = v - case "dedup": - zpool.dedupRatio = v - case "health": - zpool.health = strings.ToLower(v) - } - - if last := i+1 == len(headers); last && zpool.name != "" && zpool.health != "" { - zpools = append(zpools, zpool) - } - } - } - - if len(zpools) == 0 { - return nil, fmt.Errorf("unexpected data: missing pools") - } - - return zpools, nil -} - -func parseInt(s string) (int64, bool) { - if s == "-" { - return 0, false - } - v, err := strconv.ParseInt(s, 10, 64) - return v, err == nil -} - -func parseFloat(s string) (float64, bool) { - if s == "-" { - return 0, false - } - v, err := strconv.ParseFloat(s, 64) - return v, err == nil -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/config_schema.json b/src/go/collectors/go.d.plugin/modules/zfspool/config_schema.json deleted file mode 100644 index fcfcff1d4..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/config_schema.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "jsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ZFS Pools collector configuration", - "type": "object", - "properties": { - "update_every": { - "title": "Update every", - "description": "Data collection interval, measured in seconds.", - "type": "integer", - "minimum": 1, - "default": 10 - }, - "binary_path": { - "title": "Binary path", - "description": "Path to the `zpool` binary.", - "type": "string", - "default": "/usr/bin/zpool" - }, - "timeout": { - "title": "Timeout", - "description": "Timeout for executing the binary, specified in seconds.", - "type": "number", - "minimum": 0.5, - "default": 2 - } - }, - "required": [ - "binary_path" - ], - "additionalProperties": false, - "patternProperties": { - "^name$": {} - } - }, - "uiSchema": { - "uiOptions": { - "fullPage": true - }, - "binary_path": { - "ui:help": "If an absolute path is provided, the collector will use it directly; otherwise, it will search for the binary in directories specified in the PATH environment variable." - }, - "timeout": { - "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)." - } - } -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/exec.go b/src/go/collectors/go.d.plugin/modules/zfspool/exec.go deleted file mode 100644 index 0c155872e..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/exec.go +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - "context" - "fmt" - "os/exec" - "time" - - "github.com/netdata/netdata/go/go.d.plugin/logger" -) - -func newZpoolCLIExec(binPath string, timeout time.Duration) *zpoolCLIExec { - return &zpoolCLIExec{ - binPath: binPath, - timeout: timeout, - } -} - -type zpoolCLIExec struct { - *logger.Logger - - binPath string - timeout time.Duration -} - -func (e *zpoolCLIExec) list() ([]byte, error) { - ctx, cancel := context.WithTimeout(context.Background(), e.timeout) - defer cancel() - - cmd := exec.CommandContext(ctx, e.binPath, "list", "-p") - e.Debugf("executing '%s'", cmd) - - bs, err := cmd.Output() - if err != nil { - return nil, fmt.Errorf("error on '%s': %v", cmd, err) - } - - return bs, nil -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/init.go b/src/go/collectors/go.d.plugin/modules/zfspool/init.go deleted file mode 100644 index f640801dd..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/init.go +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - "errors" - "os" - "os/exec" - "strings" -) - -func (z *ZFSPool) validateConfig() error { - if z.BinaryPath == "" { - return errors.New("no zpool binary path specified") - } - return nil -} - -func (z *ZFSPool) initZPoolCLIExec() (zpoolCLI, error) { - binPath := z.BinaryPath - - if !strings.HasPrefix(binPath, "/") { - path, err := exec.LookPath(binPath) - if err != nil { - return nil, err - } - binPath = path - } - - if _, err := os.Stat(binPath); err != nil { - return nil, err - } - - zpoolExec := newZpoolCLIExec(binPath, z.Timeout.Duration()) - zpoolExec.Logger = z.Logger - - return zpoolExec, nil -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/integrations/zfs_pools.md b/src/go/collectors/go.d.plugin/modules/zfspool/integrations/zfs_pools.md deleted file mode 100644 index 827ae9111..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/integrations/zfs_pools.md +++ /dev/null @@ -1,169 +0,0 @@ -<!--startmeta -custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/zfspool/README.md" -meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/zfspool/metadata.yaml" -sidebar_label: "ZFS Pools" -learn_status: "Published" -learn_rel_path: "Collecting Metrics/Storage, Mount Points and Filesystems" -most_popular: False -message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE" -endmeta--> - -# ZFS Pools - - -<img src="https://netdata.cloud/img/filesystem.svg" width="150"/> - - -Plugin: go.d.plugin -Module: zfspool - -<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> - -## Overview - -This collector monitors the health and space usage of ZFS pools using the command line tool [zpool](https://openzfs.github.io/openzfs-docs/man/master/8/zpool-list.8.html). - - - - -This collector is supported on all platforms. - -This collector only supports collecting metrics from a single instance of this integration. - - -### Default Behavior - -#### Auto-Detection - -This integration doesn't support auto-detection. - -#### Limits - -The default configuration for this integration does not impose any limits on data collection. - -#### Performance Impact - -The default configuration for this integration is not expected to impose a significant performance impact on the system. - - -## Metrics - -Metrics grouped by *scope*. - -The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels. - - - -### Per zfs pool - -These metrics refer to the ZFS pool. - -Labels: - -| Label | Description | -|:-----------|:----------------| -| pool | Zpool name | - -Metrics: - -| Metric | Dimensions | Unit | -|:------|:----------|:----| -| zfspool.pool_space_utilization | utilization | % | -| zfspool.pool_space_usage | free, used | bytes | -| zfspool.pool_fragmentation | fragmentation | % | -| zfspool.pool_health_state | online, degraded, faulted, offline, unavail, removed, suspended | state | - - - -## Alerts - - -The following alerts are available: - -| Alert name | On metric | Description | -|:------------|:----------|:------------| -| [ zfs_pool_space_utilization ](https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf) | zfspool.pool_space_utilization | ZFS pool ${label:pool} is nearing capacity. Current space usage is above the threshold. | -| [ zfs_pool_health_state_warn ](https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf) | zfspool.pool_health_state | ZFS pool ${label:pool} state is degraded | -| [ zfs_pool_health_state_crit ](https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf) | zfspool.pool_health_state | ZFS pool ${label:pool} state is faulted or unavail | - - -## Setup - -### Prerequisites - -No action required. - -### Configuration - -#### File - -The configuration file name for this integration is `go.d/zfspool.conf`. - - -You can edit the configuration file using the `edit-config` script from the -Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory). - -```bash -cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata -sudo ./edit-config go.d/zfspool.conf -``` -#### Options - -The following options can be defined globally: update_every. - - -<details open><summary>Config options</summary> - -| Name | Description | Default | Required | -|:----|:-----------|:-------|:--------:| -| update_every | Data collection frequency. | 10 | no | -| binary_path | Path to the `zpool` binary. If an absolute path is provided, the collector will use it directly; otherwise, it will search for the binary in directories specified in the PATH environment variable. | /usr/bin/zpool | yes | -| timeout | Timeout for executing the binary, specified in seconds. | 2 | no | - -</details> - -#### Examples - -##### Custom binary path - -The executable is not in the directories specified in the PATH environment variable. - -<details open><summary>Config</summary> - -```yaml -jobs: - - name: zfspool - binary_path: /usr/local/sbin/zpool - -``` -</details> - - - -## Troubleshooting - -### Debug Mode - -To troubleshoot issues with the `zfspool` collector, run the `go.d.plugin` with the debug option enabled. The output -should give you clues as to why the collector isn't working. - -- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on - your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`. - - ```bash - cd /usr/libexec/netdata/plugins.d/ - ``` - -- Switch to the `netdata` user. - - ```bash - sudo -u netdata -s - ``` - -- Run the `go.d.plugin` to debug the collector: - - ```bash - ./go.d.plugin -d -m zfspool - ``` - - diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/metadata.yaml b/src/go/collectors/go.d.plugin/modules/zfspool/metadata.yaml deleted file mode 100644 index 847ee483e..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/metadata.yaml +++ /dev/null @@ -1,138 +0,0 @@ -plugin_name: go.d.plugin -modules: - - meta: - id: collector-go.d.plugin-zfspool - plugin_name: go.d.plugin - module_name: zfspool - monitored_instance: - name: ZFS Pools - link: "" - icon_filename: filesystem.svg - categories: - - data-collection.storage-mount-points-and-filesystems - keywords: - - zfs pools - - pools - - zfs - - filesystem - related_resources: - integrations: - list: [] - info_provided_to_referring_integrations: - description: "" - most_popular: false - overview: - data_collection: - metrics_description: > - This collector monitors the health and space usage of ZFS pools using the command line - tool [zpool](https://openzfs.github.io/openzfs-docs/man/master/8/zpool-list.8.html). - method_description: "" - supported_platforms: - include: [] - exclude: [] - multi_instance: false - additional_permissions: - description: "" - default_behavior: - auto_detection: - description: "" - limits: - description: "" - performance_impact: - description: "" - setup: - prerequisites: - list: [] - configuration: - file: - name: go.d/zfspool.conf - options: - description: | - The following options can be defined globally: update_every. - folding: - title: Config options - enabled: true - list: - - name: update_every - description: Data collection frequency. - default_value: 10 - required: false - - name: binary_path - description: Path to the `zpool` binary. If an absolute path is provided, the collector will use it directly; otherwise, it will search for the binary in directories specified in the PATH environment variable. - default_value: /usr/bin/zpool - required: true - - name: timeout - description: Timeout for executing the binary, specified in seconds. - default_value: 2 - required: false - examples: - folding: - title: Config - enabled: true - list: - - name: Custom binary path - description: The executable is not in the directories specified in the PATH environment variable. - config: | - jobs: - - name: zfspool - binary_path: /usr/local/sbin/zpool - troubleshooting: - problems: - list: [] - alerts: - - name: zfs_pool_space_utilization - metric: zfspool.pool_space_utilization - info: "ZFS pool ${label:pool} is nearing capacity. Current space usage is above the threshold." - link: https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf - - name: zfs_pool_health_state_warn - metric: zfspool.pool_health_state - info: "ZFS pool ${label:pool} state is degraded" - link: https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf - - name: zfs_pool_health_state_crit - metric: zfspool.pool_health_state - info: "ZFS pool ${label:pool} state is faulted or unavail" - link: https://github.com/netdata/netdata/blob/master/src/health/health.d/zfs.conf - metrics: - folding: - title: Metrics - enabled: false - description: "" - availability: [] - scopes: - - name: zfs pool - description: These metrics refer to the ZFS pool. - labels: - - name: pool - description: Zpool name - metrics: - - name: zfspool.pool_space_utilization - description: Zpool space utilization - unit: '%' - chart_type: area - dimensions: - - name: utilization - - name: zfspool.pool_space_usage - description: Zpool space usage - unit: 'bytes' - chart_type: stacked - dimensions: - - name: free - - name: used - - name: zfspool.pool_fragmentation - description: Zpool fragmentation - unit: '%' - chart_type: line - dimensions: - - name: fragmentation - - name: zfspool.pool_health_state - description: Zpool health state - unit: 'state' - chart_type: line - dimensions: - - name: online - - name: degraded - - name: faulted - - name: offline - - name: unavail - - name: removed - - name: suspended diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.json b/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.json deleted file mode 100644 index 095713193..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "update_every": 123, - "timeout": 123.123, - "binary_path": "ok" -} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.yaml b/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.yaml deleted file mode 100644 index baf3bcd0b..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -update_every: 123 -timeout: 123.123 -binary_path: "ok" diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/zpool-list.txt b/src/go/collectors/go.d.plugin/modules/zfspool/testdata/zpool-list.txt deleted file mode 100644 index 06d9915c2..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/testdata/zpool-list.txt +++ /dev/null @@ -1,3 +0,0 @@ -NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT -rpool 21367462298 9051643576 12240656794 - 33 42 1.00 ONLINE - -zion - - - - - - - FAULTED - diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/zfspool.go b/src/go/collectors/go.d.plugin/modules/zfspool/zfspool.go deleted file mode 100644 index 154aacb20..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/zfspool.go +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - _ "embed" - "errors" - "time" - - "github.com/netdata/netdata/go/go.d.plugin/agent/module" - "github.com/netdata/netdata/go/go.d.plugin/pkg/web" -) - -//go:embed "config_schema.json" -var configSchema string - -func init() { - module.Register("zfspool", module.Creator{ - JobConfigSchema: configSchema, - Defaults: module.Defaults{ - UpdateEvery: 10, - }, - Create: func() module.Module { return New() }, - Config: func() any { return &Config{} }, - }) -} - -func New() *ZFSPool { - return &ZFSPool{ - Config: Config{ - BinaryPath: "/usr/bin/zpool", - Timeout: web.Duration(time.Second * 2), - }, - charts: &module.Charts{}, - zpools: make(map[string]bool), - } -} - -type Config struct { - UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"` - Timeout web.Duration `yaml:"timeout,omitempty" json:"timeout"` - BinaryPath string `yaml:"binary_path,omitempty" json:"binary_path"` -} - -type ( - ZFSPool struct { - module.Base - Config `yaml:",inline" json:""` - - charts *module.Charts - - exec zpoolCLI - - zpools map[string]bool - } - zpoolCLI interface { - list() ([]byte, error) - } -) - -func (z *ZFSPool) Configuration() any { - return z.Config -} - -func (z *ZFSPool) Init() error { - if err := z.validateConfig(); err != nil { - z.Errorf("config validation: %s", err) - return err - } - - zpoolExec, err := z.initZPoolCLIExec() - if err != nil { - z.Errorf("zpool exec initialization: %v", err) - return err - } - z.exec = zpoolExec - - return nil -} - -func (z *ZFSPool) Check() error { - mx, err := z.collect() - if err != nil { - z.Error(err) - return err - } - - if len(mx) == 0 { - return errors.New("no metrics collected") - } - - return nil -} - -func (z *ZFSPool) Charts() *module.Charts { - return z.charts -} - -func (z *ZFSPool) Collect() map[string]int64 { - mx, err := z.collect() - if err != nil { - z.Error(err) - } - - if len(mx) == 0 { - return nil - } - - return mx -} - -func (z *ZFSPool) Cleanup() {} diff --git a/src/go/collectors/go.d.plugin/modules/zfspool/zfspool_test.go b/src/go/collectors/go.d.plugin/modules/zfspool/zfspool_test.go deleted file mode 100644 index ea40aa06d..000000000 --- a/src/go/collectors/go.d.plugin/modules/zfspool/zfspool_test.go +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -package zfspool - -import ( - "errors" - "os" - "testing" - - "github.com/netdata/netdata/go/go.d.plugin/agent/module" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var ( - dataConfigJSON, _ = os.ReadFile("testdata/config.json") - dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") - - dataZpoolList, _ = os.ReadFile("testdata/zpool-list.txt") -) - -func Test_testDataIsValid(t *testing.T) { - for name, data := range map[string][]byte{ - "dataConfigJSON": dataConfigJSON, - "dataConfigYAML": dataConfigYAML, - - "dataZpoolList": dataZpoolList, - } { - require.NotNil(t, data, name) - - } -} - -func TestZFSPool_Configuration(t *testing.T) { - module.TestConfigurationSerialize(t, &ZFSPool{}, dataConfigJSON, dataConfigYAML) -} - -func TestZFSPool_Init(t *testing.T) { - tests := map[string]struct { - config Config - wantFail bool - }{ - "fails if 'binary_path' is not set": { - wantFail: true, - config: Config{ - BinaryPath: "", - }, - }, - "fails if failed to find binary": { - wantFail: true, - config: Config{ - BinaryPath: "zpool!!!", - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - zp := New() - zp.Config = test.config - - if test.wantFail { - assert.Error(t, zp.Init()) - } else { - assert.NoError(t, zp.Init()) - } - }) - } -} - -func TestZFSPool_Cleanup(t *testing.T) { - tests := map[string]struct { - prepare func() *ZFSPool - }{ - "not initialized exec": { - prepare: func() *ZFSPool { - return New() - }, - }, - "after check": { - prepare: func() *ZFSPool { - zp := New() - zp.exec = prepareMockOK() - _ = zp.Check() - return zp - }, - }, - "after collect": { - prepare: func() *ZFSPool { - zp := New() - zp.exec = prepareMockOK() - _ = zp.Collect() - return zp - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - zp := test.prepare() - - assert.NotPanics(t, zp.Cleanup) - }) - } -} - -func TestZFSPool_Charts(t *testing.T) { - assert.NotNil(t, New().Charts()) -} - -func TestZFSPool_Check(t *testing.T) { - tests := map[string]struct { - prepareMock func() *mockZpoolCLIExec - wantFail bool - }{ - "success case": { - prepareMock: prepareMockOK, - wantFail: false, - }, - "error on list call": { - prepareMock: prepareMockErrOnList, - wantFail: true, - }, - "empty response": { - prepareMock: prepareMockEmptyResponse, - wantFail: true, - }, - "unexpected response": { - prepareMock: prepareMockUnexpectedResponse, - wantFail: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - zp := New() - mock := test.prepareMock() - zp.exec = mock - - if test.wantFail { - assert.Error(t, zp.Check()) - } else { - assert.NoError(t, zp.Check()) - } - }) - } -} - -func TestZFSPool_Collect(t *testing.T) { - tests := map[string]struct { - prepareMock func() *mockZpoolCLIExec - wantMetrics map[string]int64 - }{ - "success case": { - prepareMock: prepareMockOK, - wantMetrics: map[string]int64{ - "zpool_rpool_alloc": 9051643576, - "zpool_rpool_cap": 42, - "zpool_rpool_frag": 33, - "zpool_rpool_free": 12240656794, - "zpool_rpool_health_state_degraded": 0, - "zpool_rpool_health_state_faulted": 0, - "zpool_rpool_health_state_offline": 0, - "zpool_rpool_health_state_online": 1, - "zpool_rpool_health_state_removed": 0, - "zpool_rpool_health_state_suspended": 0, - "zpool_rpool_health_state_unavail": 0, - "zpool_rpool_size": 21367462298, - "zpool_zion_health_state_degraded": 0, - "zpool_zion_health_state_faulted": 1, - "zpool_zion_health_state_offline": 0, - "zpool_zion_health_state_online": 0, - "zpool_zion_health_state_removed": 0, - "zpool_zion_health_state_suspended": 0, - "zpool_zion_health_state_unavail": 0, - }, - }, - "error on list call": { - prepareMock: prepareMockErrOnList, - wantMetrics: nil, - }, - "empty response": { - prepareMock: prepareMockEmptyResponse, - wantMetrics: nil, - }, - "unexpected response": { - prepareMock: prepareMockUnexpectedResponse, - wantMetrics: nil, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - zp := New() - mock := test.prepareMock() - zp.exec = mock - - mx := zp.Collect() - - assert.Equal(t, test.wantMetrics, mx) - if len(test.wantMetrics) > 0 { - assert.Len(t, *zp.Charts(), len(zpoolChartsTmpl)*len(zp.zpools)) - } - }) - } -} - -func prepareMockOK() *mockZpoolCLIExec { - return &mockZpoolCLIExec{ - listData: dataZpoolList, - } -} - -func prepareMockErrOnList() *mockZpoolCLIExec { - return &mockZpoolCLIExec{ - errOnList: true, - } -} - -func prepareMockEmptyResponse() *mockZpoolCLIExec { - return &mockZpoolCLIExec{} -} - -func prepareMockUnexpectedResponse() *mockZpoolCLIExec { - return &mockZpoolCLIExec{ - listData: []byte(` -Lorem ipsum dolor sit amet, consectetur adipiscing elit. -Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus. -Fusce et felis pulvinar, posuere sem non, porttitor eros. -`), - } -} - -type mockZpoolCLIExec struct { - errOnList bool - listData []byte -} - -func (m *mockZpoolCLIExec) list() ([]byte, error) { - if m.errOnList { - return nil, errors.New("mock.list() error") - } - - return m.listData, nil -} |