summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/lvm/collect.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/lvm/collect.go')
-rw-r--r--src/go/collectors/go.d.plugin/modules/lvm/collect.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/lvm/collect.go b/src/go/collectors/go.d.plugin/modules/lvm/collect.go
new file mode 100644
index 0000000000..8f57a1a807
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/lvm/collect.go
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package lvm
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+)
+
+type lvsReport struct {
+ Report []struct {
+ Lv []struct {
+ VGName string `json:"vg_name"`
+ LVName string `json:"lv_name"`
+ LVSize string `json:"lv_size"`
+ DataPercent string `json:"data_percent"`
+ MetadataPercent string `json:"metadata_percent"`
+ LVAttr string `json:"lv_attr"`
+ } `json:"lv"`
+ } `json:"report"`
+}
+
+func (l *LVM) collect() (map[string]int64, error) {
+ bs, err := l.exec.lvsReportJson()
+ if err != nil {
+ return nil, err
+ }
+
+ var report lvsReport
+ if err = json.Unmarshal(bs, &report); err != nil {
+ return nil, err
+ }
+
+ mx := make(map[string]int64)
+
+ for _, r := range report.Report {
+ for _, lv := range r.Lv {
+ if lv.VGName == "" || lv.LVName == "" {
+ continue
+ }
+
+ if !isThinPool(lv.LVAttr) {
+ l.Debugf("skipping lv '%s' vg '%s': not a thin pool", lv.LVName, lv.VGName)
+ continue
+ }
+
+ key := fmt.Sprintf("lv_%s_vg_%s", lv.LVName, lv.VGName)
+ if !l.lvmThinPools[key] {
+ l.addLVMThinPoolCharts(lv.LVName, lv.VGName)
+ l.lvmThinPools[key] = true
+ }
+ if v, ok := parseFloat(lv.DataPercent); ok {
+ mx[key+"_data_percent"] = int64(v * 100)
+ }
+ if v, ok := parseFloat(lv.MetadataPercent); ok {
+ mx[key+"_metadata_percent"] = int64(v * 100)
+ }
+ }
+ }
+
+ return mx, nil
+}
+
+func isThinPool(lvAttr string) bool {
+ return getLVType(lvAttr) == "thin_pool"
+}
+
+func getLVType(lvAttr string) string {
+ if len(lvAttr) == 0 {
+ return ""
+ }
+
+ // https://man7.org/linux/man-pages/man8/lvs.8.html#NOTES
+ switch lvAttr[0] {
+ case 'C':
+ return "cache"
+ case 'm':
+ return "mirrored"
+ case 'M':
+ return "mirrored_without_initial_sync"
+ case 'o':
+ return "origin"
+ case 'O':
+ return "origin_with_merging_snapshot"
+ case 'g':
+ return "integrity"
+ case 'r':
+ return "raid"
+ case 'R':
+ return "raid_without_initial_sync"
+ case 's':
+ return "snapshot"
+ case 'S':
+ return "merging_snapshot"
+ case 'p':
+ return "pvmove"
+ case 'v':
+ return "virtual"
+ case 'i':
+ return "mirror_or_raid_image"
+ case 'I':
+ return "mirror_or_raid_mage_out_of_sync"
+ case 'l':
+ return "log_device"
+ case 'c':
+ return "under_conversion"
+ case 'V':
+ return "thin_volume"
+ case 't':
+ return "thin_pool"
+ case 'T':
+ return "thin_pool_data"
+ case 'd':
+ return "vdo_pool"
+ case 'D':
+ return "vdo_pool_data"
+ case 'e':
+ return "raid_or_pool_metadata"
+ default:
+ return ""
+ }
+}
+
+func parseFloat(s string) (float64, bool) {
+ if s == "-" {
+ return 0, false
+ }
+ v, err := strconv.ParseFloat(s, 64)
+ return v, err == nil
+}