mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 01:59:04 +02:00
mscluster: accept short resource class information (#2669)
Co-authored-by: EisenbergD <dominik.eisenberg@beiersdorf.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: EisenbergD <dominik.eisenberg@beiersdorf.com>
This commit is contained in:
co-authored by
EisenbergD
Claude Opus 5.5
parent
4e6cbf864c
commit
adc9183cf6
@@ -515,14 +515,10 @@ func readResource(handle uintptr, resource *Resource, deadline time.Time) error
|
||||
}
|
||||
|
||||
data, err := resourceBuffer(handle, resourceGetClassInfo, 8, deadline)
|
||||
switch {
|
||||
case err != nil:
|
||||
if err != nil {
|
||||
resultErr = errors.Join(resultErr, fmt.Errorf("class information: %w", err))
|
||||
case len(data) != 8:
|
||||
resultErr = errors.Join(resultErr, errors.New("invalid resource class information size"))
|
||||
default:
|
||||
resource.Values["ResourceClass"] = binary.LittleEndian.Uint32(data)
|
||||
resource.Values["Subclass"] = binary.LittleEndian.Uint32(data[4:])
|
||||
} else {
|
||||
resource.Values["ResourceClass"], resource.Values["Subclass"] = parseResourceClassInfo(data)
|
||||
}
|
||||
|
||||
// The property lists normally carry the type; only ask separately without it.
|
||||
@@ -548,6 +544,25 @@ func readResource(handle uintptr, resource *Resource, deadline time.Time) error
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// parseResourceClassInfo decodes CLUS_RESOURCE_CLASS_INFO. Some resource DLLs,
|
||||
// such as the Storage Spaces Direct Health Service, succeed but return only
|
||||
// the class DWORD without the subclass; the WMI provider reports their
|
||||
// ResourceClass as CLUS_RESCLASS_UNKNOWN (0), so missing fields decode as 0
|
||||
// instead of failing.
|
||||
func parseResourceClassInfo(data []byte) (uint32, uint32) {
|
||||
var class, subclass uint32
|
||||
|
||||
if len(data) >= 4 {
|
||||
class = binary.LittleEndian.Uint32(data)
|
||||
}
|
||||
|
||||
if len(data) >= 8 {
|
||||
subclass = binary.LittleEndian.Uint32(data[4:])
|
||||
}
|
||||
|
||||
return class, subclass
|
||||
}
|
||||
|
||||
func resourceBuffer(handle uintptr, code uint32, size int, deadline time.Time) ([]byte, error) {
|
||||
return controlBuffer(deadline, size, func(buffer []byte) (uint32, error) {
|
||||
var (
|
||||
|
||||
@@ -269,3 +269,27 @@ func TestUnopenedClusterExpiredBudget(t *testing.T) {
|
||||
t.Fatal("unopened cluster was not closed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseResourceClassInfo(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
data []byte
|
||||
class uint32
|
||||
subclass uint32
|
||||
}{
|
||||
{"complete", []byte{1, 0, 0, 0, 0, 0, 0, 0x80}, 1, 0x80000000},
|
||||
// Captured from the Storage Spaces Direct Health Service resource: only
|
||||
// the class DWORD, without the subclass. WMI reports ResourceClass 0.
|
||||
{"health service", []byte{0, 0, 0, 0}, 0, 0},
|
||||
{"empty", nil, 0, 0},
|
||||
{"class only", []byte{2, 0, 0, 0}, 2, 0},
|
||||
{"truncated class", []byte{1, 0}, 0, 0},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
class, subclass := parseResourceClassInfo(test.data)
|
||||
if class != test.class || subclass != test.subclass {
|
||||
t.Fatalf("class=%#x subclass=%#x, want %#x/%#x", class, subclass, test.class, test.subclass)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package clusapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -163,11 +162,9 @@ func (c *Cluster) resourceClass(name string, deadline time.Time) (_ uint32, resu
|
||||
return 0, fmt.Errorf("class information: %w", err)
|
||||
}
|
||||
|
||||
if len(data) != 8 {
|
||||
return 0, errors.New("invalid resource class information size")
|
||||
}
|
||||
class, _ := parseResourceClassInfo(data)
|
||||
|
||||
return binary.LittleEndian.Uint32(data), nil
|
||||
return class, nil
|
||||
}
|
||||
|
||||
// readClusterName calls GetClusterInformation without CLUSTERVERSIONINFO.
|
||||
|
||||
@@ -100,11 +100,7 @@ func (c *Cluster) readResourcePartitions(name objectName, deadline time.Time) (_
|
||||
return nil, fmt.Errorf("class information: %w", err)
|
||||
}
|
||||
|
||||
if len(data) != 8 {
|
||||
return nil, errors.New("invalid resource class information size")
|
||||
}
|
||||
|
||||
if binary.LittleEndian.Uint32(data) != resourceClassStorage {
|
||||
if class, _ := parseResourceClassInfo(data); class != resourceClassStorage {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user