test(ilm): check the purge's history error end to end

The implementation review of the delete-all reporting found that no
committed test checked the error a purge returns on a drive whose
metadata does not decode: restoring the old read quorum error passed.
TestPurgeAllVersionsRefusesCorruptDrive now sends the purge through
DeleteObject and checks errDeleteAllHistoryUnavailable and its
SlowDownWrite mapping; with the old error it fails.

The HELP text of expiry_incomplete_total now says that the
tier_unsupported_skipped reason counts the scanner's per-drive
observations, not expiry attempts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-11-06 20:28:55 +08:00
parent 7af07298ce
commit db0c0ffedd
3 changed files with 7 additions and 2 deletions
@@ -170,6 +170,11 @@ func TestPurgeAllVersionsRefusesCorruptDrive(t *testing.T) {
if delta[ilmIncompleteHistoryUnavailable] != 1 {
t.Errorf("counted %v, want one %s", delta, ilmIncompleteHistoryUnavailable)
}
// The purge names the cause, and callers see a write quorum error.
_, err = z.DeleteObject(ctx, p.bucket, key, ObjectOptions{DeleteAllVersions: true, Expiration: ExpirationOptions{Expire: true}})
if !errors.Is(err, errDeleteAllHistoryUnavailable) || toAPIErrorCode(ctx, err) != ErrSlowDownWrite {
t.Errorf("purge on a corrupt drive: %v, want %v as SlowDownWrite", err, errDeleteAllHistoryUnavailable)
}
if got := p.get(key); got != "v2" {
t.Fatalf("the refused purge left %s readable", got)
}
+1 -1
View File
@@ -2143,7 +2143,7 @@ func getILMNodeMetrics() *MetricsGroupV2 {
Namespace: nodeMetricNamespace,
Subsystem: ilmSubsystem,
Name: expiryIncompleteTotal,
Help: "Total number of ILM expiry attempts since server start that ended without removing what they addressed, by reason",
Help: "Total number of ILM expiry attempts since server start that ended without removing what they addressed, by reason; tier_unsupported_skipped counts the scanner's per-drive observations of an expiry of all versions it did not queue",
Type: counterMetric,
},
VariableLabels: map[string]string{"reason": reason},
+1 -1
View File
@@ -36,7 +36,7 @@ var (
ilmTransitionPendingTasksMD = NewGaugeMD(transitionPendingTasks, "Number of pending ILM transition tasks in the queue")
ilmTransitionMissedImmediateTasksMD = NewCounterMD(transitionMissedImmediateTasks, "Number of missed immediate ILM transition tasks")
ilmVersionsScannedMD = NewCounterMD(versionsScanned, "Total number of object versions checked for ILM actions since server start")
ilmExpiryIncompleteTotalMD = NewCounterMD(expiryIncompleteTotal, "Total number of ILM expiry attempts since server start that ended without removing what they addressed, by reason", "reason")
ilmExpiryIncompleteTotalMD = NewCounterMD(expiryIncompleteTotal, "Total number of ILM expiry attempts since server start that ended without removing what they addressed, by reason; tier_unsupported_skipped counts the scanner's per-drive observations of an expiry of all versions it did not queue", "reason")
)
// loadILMMetrics - `MetricsLoaderFn` for ILM metrics.