Ensure sensor proxy wrapper delivers SMART temps locally
This commit is contained in:
parent
30a069dfa6
commit
335795d354
2 changed files with 50 additions and 5 deletions
|
|
@ -25,6 +25,19 @@ const (
|
|||
tempWrapperScript = `#!/bin/sh
|
||||
set -eu
|
||||
|
||||
WRAPPER_PATH="${PULSE_SENSOR_WRAPPER:-/opt/pulse/sensor-proxy/bin/pulse-sensor-wrapper.sh}"
|
||||
|
||||
# Prefer the full wrapper when available so SMART disk temperatures are included
|
||||
if [ -x "$WRAPPER_PATH" ]; then
|
||||
exec "$WRAPPER_PATH"
|
||||
fi
|
||||
|
||||
# Legacy locations (for older installations)
|
||||
if [ -x /usr/local/bin/pulse-sensor-wrapper.sh ]; then
|
||||
exec /usr/local/bin/pulse-sensor-wrapper.sh
|
||||
fi
|
||||
|
||||
# Fallback to basic lm-sensors output (no SMART data)
|
||||
if command -v sensors >/dev/null 2>&1; then
|
||||
OUTPUT="$(sensors -j 2>/dev/null || true)"
|
||||
if [ -n "$OUTPUT" ]; then
|
||||
|
|
@ -575,12 +588,10 @@ func (p *Proxy) testSSHConnection(nodeHost string) error {
|
|||
func (p *Proxy) getTemperatureViaSSH(ctx context.Context, nodeHost string) (string, error) {
|
||||
startTime := time.Now()
|
||||
nodeLabel := sanitizeNodeLabel(nodeHost)
|
||||
localNode := isLocalNode(nodeHost)
|
||||
|
||||
// Check if we're requesting the local node (self-monitoring)
|
||||
// For standalone nodes, avoid SSH and run sensors directly
|
||||
if isLocalNode(nodeHost) {
|
||||
log.Debug().Str("node", nodeHost).Msg("Self-monitoring detected, collecting temperatures locally")
|
||||
return p.getTemperatureLocal(ctx)
|
||||
if localNode {
|
||||
log.Debug().Str("node", nodeHost).Msg("Self-monitoring detected, using SSH wrapper for SMART temperatures")
|
||||
}
|
||||
|
||||
privKeyPath := filepath.Join(p.sshKeyPath, "id_ed25519")
|
||||
|
|
@ -617,6 +628,19 @@ func (p *Proxy) getTemperatureViaSSH(ctx context.Context, nodeHost string) (stri
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
if localNode {
|
||||
log.Warn().
|
||||
Str("node", nodeHost).
|
||||
Err(err).
|
||||
Msg("SSH temperature collection failed on local node, falling back to direct sensors")
|
||||
|
||||
if fallback, localErr := p.getTemperatureLocal(ctx); localErr == nil && strings.TrimSpace(fallback) != "" {
|
||||
p.metrics.sshRequests.WithLabelValues(nodeLabel, "success").Inc()
|
||||
p.metrics.sshLatency.WithLabelValues(nodeLabel).Observe(time.Since(startTime).Seconds())
|
||||
return fallback, nil
|
||||
}
|
||||
}
|
||||
|
||||
p.metrics.sshRequests.WithLabelValues(nodeLabel, "error").Inc()
|
||||
p.metrics.sshLatency.WithLabelValues(nodeLabel).Observe(time.Since(startTime).Seconds())
|
||||
stderrMsg := strings.TrimSpace(stderr)
|
||||
|
|
|
|||
|
|
@ -138,6 +138,27 @@ func TestTempWrapperPrefersSensorsOutput(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTempWrapperPrefersOverrideWrapper(t *testing.T) {
|
||||
scriptPath, _, binDir, baseDir := setupTempWrapper(t)
|
||||
|
||||
overrideDir := filepath.Join(baseDir, "override")
|
||||
if err := os.MkdirAll(overrideDir, 0o755); err != nil {
|
||||
t.Fatalf("failed to create override directory: %v", err)
|
||||
}
|
||||
|
||||
overridePath := filepath.Join(overrideDir, "pulse-sensor-wrapper.sh")
|
||||
expectedOutput := `{"smart":[{"device":"/dev/test","temperature":42}]}`
|
||||
overrideScript := fmt.Sprintf("#!/bin/sh\nprintf '%s'\n", expectedOutput)
|
||||
if err := os.WriteFile(overridePath, []byte(overrideScript), 0o755); err != nil {
|
||||
t.Fatalf("failed to write override wrapper: %v", err)
|
||||
}
|
||||
|
||||
output := runTempWrapper(t, scriptPath, binDir, "PULSE_SENSOR_WRAPPER="+overridePath)
|
||||
if strings.TrimSpace(string(output)) != expectedOutput {
|
||||
t.Fatalf("expected override wrapper output %s, got %s", expectedOutput, strings.TrimSpace(string(output)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAllWithLimit(t *testing.T) {
|
||||
reader := bytes.NewBufferString("abcdefg")
|
||||
data, exceeded, err := readAllWithLimit(reader, 4)
|
||||
|
|
|
|||
Loading…
Reference in a new issue