From e1fd6787ab1957dd99abaaee8c81ae2d95120c5c Mon Sep 17 00:00:00 2001 From: Ahmet Oeztuerk Date: Tue, 30 Jun 2026 11:39:59 +0200 Subject: [PATCH 1/3] check_drivesize: fix drives without assigned letters having an empty name, which resulted in perfdata only having the attribute seemingly without drive name prefix found with ai, did not test on the misbehaving system --- pkg/snclient/check_drivesize_windows.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/snclient/check_drivesize_windows.go b/pkg/snclient/check_drivesize_windows.go index c8e82e6a..860cd239 100644 --- a/pkg/snclient/check_drivesize_windows.go +++ b/pkg/snclient/check_drivesize_windows.go @@ -348,6 +348,16 @@ func (l *CheckDrivesize) setDeviceInfo(drive map[string]string) { if drive["drive_or_name"] == "" { drive["drive_or_name"] = driveOrName } + + // volumes without an assigned drive letter have empty drive["drive"] + // use the volume name or id as fallback + if drive["drive"] == "" { + if drive["name"] != "" { + drive["drive"] = drive["name"] + } else { + drive["drive"] = drive["drive_or_id"] + } + } } // gopsutil disk.Partition had an issue with Bitlocker, but a fix was upstreamed From c9cdd5472cad84876aed0507d6b028479143fdb3 Mon Sep 17 00:00:00 2001 From: Ahmet Ozturk Date: Wed, 8 Jul 2026 17:30:27 +0200 Subject: [PATCH 2/3] check_drivesize: define and use "drive_or_name_or_id" attribute for perfdata label prefix --- pkg/snclient/check_drivesize.go | 19 +++++++++------- pkg/snclient/check_drivesize_other.go | 1 + pkg/snclient/check_drivesize_windows.go | 30 ++++++++++++------------- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/pkg/snclient/check_drivesize.go b/pkg/snclient/check_drivesize.go index 146fc3df..713ccfe4 100644 --- a/pkg/snclient/check_drivesize.go +++ b/pkg/snclient/check_drivesize.go @@ -113,6 +113,7 @@ func (l *CheckDrivesize) Build() *CheckData { {name: "id", description: "Drive or id of drive"}, {name: "drive_or_id", description: "Drive letter if present if not use id"}, {name: "drive_or_name", description: "Drive letter if present if not use name"}, + {name: "drive_or_name_or_id", description: "Drive letter if present, if not use drive name, if not use the given ID. Useful for volumes without assigned letters on Windows."}, {name: "fstype", description: "Filesystem type"}, {name: "mounted", description: "Flag whether drive is mounter (0/1)", unit: UBool}, @@ -298,7 +299,7 @@ func (l *CheckDrivesize) isExcluded(drive map[string]string, excludes []string) return false } -func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk.UsageStat, magic float64) { +func (l *CheckDrivesize) addMetrics(metricPrefix string, check *CheckData, usage *disk.UsageStat, magic float64) { total := usage.Total if !l.freespaceIgnoreReserved { total = usage.Used + usage.Free // use this total instead of usage.Total to account in the root reserved space @@ -307,16 +308,16 @@ func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk. if check.HasThreshold("free") || check.HasThreshold("free_pct") || check.HasThreshold("free_bytes") { check.warnThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes"}, "free", check.warnThreshold) check.critThreshold = check.TransformMultipleKeywords([]string{"free_pct", "free_bytes"}, "free", check.critThreshold) - check.AddBytePercentMetrics("free", drive+" free", magic*float64(usage.Free), magic*float64(total)) + check.AddBytePercentMetrics("free", metricPrefix+" free", magic*float64(usage.Free), magic*float64(total)) } // convert ' used_pct' keywords in conditions to ' used %' as that matches the metric name - convertDriveUsagePctMetric1 := fmt.Sprintf("%s used_pct", drive) + convertDriveUsagePctMetric1 := fmt.Sprintf("%s used_pct", metricPrefix) // metrics are normally added if the operand is simply 'used' , 'used_pct' , 'used_bytes' etc. and do not have a drive prefix // detect conditions where the operand is named ' used %', this is the default way snclient names percent usage metrics. // if there is a condition using that as an operand, add usage metrics for that drive as well. during the metrics condition checking, they will take effect. // this helps to check usage metrics specific to drives. - driveUsagePctMetric := fmt.Sprintf("%s used %%", drive) + driveUsagePctMetric := fmt.Sprintf("%s used %%", metricPrefix) check.warnThreshold = check.TransformMultipleKeywords([]string{convertDriveUsagePctMetric1}, driveUsagePctMetric, check.warnThreshold) check.critThreshold = check.TransformMultipleKeywords([]string{convertDriveUsagePctMetric1}, driveUsagePctMetric, check.critThreshold) @@ -324,17 +325,17 @@ func (l *CheckDrivesize) addMetrics(drive string, check *CheckData, usage *disk. if check.HasThreshold(driveUsagePctMetric) || check.HasThreshold("used") || check.HasThreshold("used_pct") || check.HasThreshold("used_bytes") { check.warnThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes"}, "used", check.warnThreshold) check.critThreshold = check.TransformMultipleKeywords([]string{"used_pct", "used_bytes"}, "used", check.critThreshold) - check.AddBytePercentMetrics("used", drive+" used", magic*float64(usage.Used), magic*float64(total)) + check.AddBytePercentMetrics("used", metricPrefix+" used", magic*float64(usage.Used), magic*float64(total)) } if check.HasThreshold("inodes") || check.HasThreshold("inodes_used") || check.HasThreshold("inodes_used_pct") { check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used"}, "inodes", check.warnThreshold) check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_used_pct", "inodes_used"}, "inodes", check.critThreshold) - check.AddPercentMetrics("inodes", drive+" inodes", float64(usage.InodesUsed), float64(usage.InodesTotal)) + check.AddPercentMetrics("inodes", metricPrefix+" inodes", float64(usage.InodesUsed), float64(usage.InodesTotal)) } if check.HasThreshold("inodes_free") || check.HasThreshold("inodes_free_pct") { check.warnThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct"}, "inodes_free", check.warnThreshold) check.critThreshold = check.TransformMultipleKeywords([]string{"inodes_free_pct"}, "inodes_free", check.critThreshold) - check.AddPercentMetrics("inodes_free", drive+" inodes free", float64(usage.InodesFree), float64(usage.InodesTotal)) + check.AddPercentMetrics("inodes_free", metricPrefix+" inodes free", float64(usage.InodesFree), float64(usage.InodesTotal)) } } @@ -452,7 +453,9 @@ func (l *CheckDrivesize) addDriveSizeDetails(check *CheckData, drive map[string] return } - l.addMetrics(drive["drive"], check, usage, magic) + // volumes without an assigned drive letter have empty drive["drive"] + // use the volume name or id as fallback + l.addMetrics(drive["drive_or_name_or_id"], check, usage, magic) } func (l *CheckDrivesize) getFlagNames(drive map[string]string) []string { diff --git a/pkg/snclient/check_drivesize_other.go b/pkg/snclient/check_drivesize_other.go index e6c789c8..cf0b1ebc 100644 --- a/pkg/snclient/check_drivesize_other.go +++ b/pkg/snclient/check_drivesize_other.go @@ -81,6 +81,7 @@ func (l *CheckDrivesize) setDisks(requiredDisks map[string]map[string]string) (e entry["drive"] = drive entry["drive_or_id"] = drive entry["drive_or_name"] = drive + drive["drive_or_name_or_id"] = drive entry["fstype"] = partition.Fstype requiredDisks[drive] = entry } diff --git a/pkg/snclient/check_drivesize_windows.go b/pkg/snclient/check_drivesize_windows.go index 860cd239..724b8182 100644 --- a/pkg/snclient/check_drivesize_windows.go +++ b/pkg/snclient/check_drivesize_windows.go @@ -325,10 +325,24 @@ func (l *CheckDrivesize) setDeviceInfo(drive map[string]string) { } name := syscall.UTF16ToString(volumeName) + drive["name"] = name + driveOrName := drive["drive"] if driveOrName == "" { driveOrName = name } + if drive["drive_or_name"] == "" { + drive["drive_or_name"] = driveOrName + } + + driveOrNameOrID := driveOrName + if driveOrNameOrID == "" { + driveOrNameOrID = drive["drive_or_id"] + } + if drive["drive_or_name_or_id"] == "" { + drive["drive_or_name_or_id"] = driveOrNameOrID + } + drive["readable"] = "1" if fileSystemFlags&volumeOptReadOnly == 0 { drive["writable"] = "1" @@ -339,25 +353,11 @@ func (l *CheckDrivesize) setDeviceInfo(drive map[string]string) { if fileSystemFlags&volumeCompressed == 0 { opts = append(opts, "compress") } - drive["opts"] = strings.Join(opts, ",") - drive["name"] = name + if drive["fstype"] == "" { drive["fstype"] = syscall.UTF16ToString(fileSystemName) } - if drive["drive_or_name"] == "" { - drive["drive_or_name"] = driveOrName - } - - // volumes without an assigned drive letter have empty drive["drive"] - // use the volume name or id as fallback - if drive["drive"] == "" { - if drive["name"] != "" { - drive["drive"] = drive["name"] - } else { - drive["drive"] = drive["drive_or_id"] - } - } } // gopsutil disk.Partition had an issue with Bitlocker, but a fix was upstreamed From d0c40588e60dca5e8f326217c3b2c996da599e4b Mon Sep 17 00:00:00 2001 From: Ahmet Oeztuerk Date: Wed, 8 Jul 2026 17:33:31 +0200 Subject: [PATCH 3/3] citest fixes: generate docs and fix compilation issue --- docs/checks/commands/check_drivesize.md | 1 + pkg/snclient/check_drivesize_other.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/checks/commands/check_drivesize.md b/docs/checks/commands/check_drivesize.md index 4bf3dabb..6148a89e 100644 --- a/docs/checks/commands/check_drivesize.md +++ b/docs/checks/commands/check_drivesize.md @@ -92,6 +92,7 @@ these can be used in filters and thresholds (along with the default attributes): | id | Drive or id of drive | | drive_or_id | Drive letter if present if not use id | | drive_or_name | Drive letter if present if not use name | +| drive_or_name_or_id | Drive letter if present, if not use drive name, if not use the given ID. Useful for volumes without assigned letters on Windows. | | fstype | Filesystem type | | mounted | Flag whether drive is mounter (0/1) | | free | Free (human readable) bytes | diff --git a/pkg/snclient/check_drivesize_other.go b/pkg/snclient/check_drivesize_other.go index cf0b1ebc..02288aad 100644 --- a/pkg/snclient/check_drivesize_other.go +++ b/pkg/snclient/check_drivesize_other.go @@ -81,7 +81,7 @@ func (l *CheckDrivesize) setDisks(requiredDisks map[string]map[string]string) (e entry["drive"] = drive entry["drive_or_id"] = drive entry["drive_or_name"] = drive - drive["drive_or_name_or_id"] = drive + entry["drive_or_name_or_id"] = drive entry["fstype"] = partition.Fstype requiredDisks[drive] = entry }