Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions src/control/cmd/dmg/pretty/check.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// (C) Copyright 2020-2023 Intel Corporation.
// (C) Copyright 2025 Hewlett Packard Enterprise Development LP
// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
Expand All @@ -16,6 +16,7 @@ import (

"github.com/daos-stack/daos/src/control/common"
"github.com/daos-stack/daos/src/control/lib/control"
"github.com/daos-stack/daos/src/control/lib/ranklist"
"github.com/daos-stack/daos/src/control/lib/txtfmt"
)

Expand Down Expand Up @@ -73,15 +74,76 @@ func countResultPools(resp *control.SystemCheckQueryResp) (int, int) {
return len(checkedMap), len(uncheckedMap)
}

func printSystemCheckTargetInfo(out io.Writer, targets []*control.SystemCheckTargetInfo) {
byRank := make(map[ranklist.Rank]map[string][]*control.SystemCheckTargetInfo)
allStatus := make(map[string]struct{})

for _, t := range targets {
if _, ok := byRank[t.Rank]; !ok {
byRank[t.Rank] = make(map[string][]*control.SystemCheckTargetInfo)
}
byRank[t.Rank][t.Status] = append(byRank[t.Rank][t.Status], t)
allStatus[t.Status] = struct{}{}
}

sortedRanks := make([]ranklist.Rank, 0, len(byRank))
for r := range byRank {
sortedRanks = append(sortedRanks, r)
}
sort.Slice(sortedRanks, func(i, j int) bool {
return sortedRanks[i] < sortedRanks[j]
})

sortedStatus := make([]string, 0, len(allStatus))
for s := range allStatus {
sortedStatus = append(sortedStatus, s)
}
sort.Slice(sortedStatus, func(i, j int) bool {
return sortedStatus[i] < sortedStatus[j]
})

condensedTargetString := func(targets []*control.SystemCheckTargetInfo) string {
targetSet := ranklist.NewRankSet()
for _, target := range targets {
targetSet.Add(ranklist.Rank(target.Target))
}
if len(targets) == 1 {
return "[" + targetSet.String() + "]"
}
return targetSet.RangedString()
}

iw := txtfmt.NewIndentWriter(out)
for _, r := range sortedRanks {
fmt.Fprintf(iw, "Rank %d target status:\n", r)

iw2 := txtfmt.NewIndentWriter(iw)
statusMap := byRank[r]
for _, s := range sortedStatus {
targets, ok := statusMap[s]
if !ok {
continue
}

fmt.Fprintf(iw2, "%s: %s\n", s, condensedTargetString(targets))
Comment on lines +123 to +128

@tanabarr tanabarr Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
targets, ok := statusMap[s]
if !ok {
continue
}
fmt.Fprintf(iw2, "%s: %s\n", s, condensedTargetString(targets))
if targets, ok := statusMap[s]; ok {
fmt.Fprintf(iw2, "%s: %s\n", s, condensedTargetString(targets))
}

}
}
}

func printSystemCheckPoolInfo(out io.Writer, pools []*control.SystemCheckPoolInfo, verbose bool) {
if verbose {
fmt.Fprintln(out, "\nPer-Pool Checker Info:")
} else {
fmt.Fprintln(out, "\nUnchecked Pools:")
}
for _, pool := range pools {
iw := txtfmt.NewIndentWriter(out)
if verbose || pool.Unchecked() {
fmt.Fprintf(out, " %+v\n", pool)
fmt.Fprintf(iw, "%+v\n", pool)

if verbose {
printSystemCheckTargetInfo(iw, pool.Targets)
}
}
}
}
Expand Down Expand Up @@ -241,6 +303,10 @@ func printInconsistencyReportsVerbose(out io.Writer, resp *control.SystemCheckQu
fmt.Fprintf(iw, "ID: 0x%x\n", report.Seq)
fmt.Fprintf(iw, "Class: %s\n", cls)
fmt.Fprintf(iw, "Message: %s\n", report.Msg)
if ranklist.Rank(report.Rank) != ranklist.NilRank {
fmt.Fprintf(iw, "Rank: %d\n", report.Rank)
fmt.Fprintf(iw, "Target: %d\n", report.Target)
Comment thread
knard38 marked this conversation as resolved.
}
fmt.Fprintf(iw, "Pool: %s\n", checkerPoolID(report, true))
if report.ContUuid != "" {
fmt.Fprintf(iw, "Container: %s\n", checkerContID(report, true))
Expand Down
96 changes: 95 additions & 1 deletion src/control/cmd/dmg/pretty/check_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// (C) Copyright 2023 Intel Corporation.
// (C) Copyright 2025 Hewlett Packard Enterprise Development LP
// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
Expand All @@ -16,8 +16,10 @@ import (
"github.com/google/go-cmp/cmp"

"github.com/daos-stack/daos/src/control/cmd/dmg/pretty"
"github.com/daos-stack/daos/src/control/common/proto/chk"
chkpb "github.com/daos-stack/daos/src/control/common/proto/chk"
"github.com/daos-stack/daos/src/control/lib/control"
"github.com/daos-stack/daos/src/control/lib/ranklist"
)

func TestPretty_PrintCheckQueryResp(t *testing.T) {
Expand Down Expand Up @@ -81,23 +83,86 @@ No reports to display.
Status: chkpb.CheckPoolStatus_CPS_CHECKED.String(),
Phase: chkpb.CheckScanPhase_CSP_DONE.String(),
StartTime: checkTime,
Targets: []*control.SystemCheckTargetInfo{
{
Target: 1,
Status: chk.CheckInstStatus_CIS_FAILED.String(),
},
{
Target: 2,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
{
Target: 3,
Rank: 1,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
},
},
"pool-2": {
UUID: "pool-2",
Status: chkpb.CheckPoolStatus_CPS_CHECKED.String(),
Phase: chkpb.CheckScanPhase_CSP_DONE.String(),
StartTime: checkTime,
Targets: []*control.SystemCheckTargetInfo{
{
Target: 4,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
{
Target: 5,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
{
Target: 6,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
},
},
"pool-3": {
UUID: "pool-3",
Status: chkpb.CheckPoolStatus_CPS_CHECKED.String(),
Phase: chkpb.CheckScanPhase_CSP_DONE.String(),
StartTime: checkTime,
Targets: []*control.SystemCheckTargetInfo{
{
Rank: 3,
Target: 7,
Status: chk.CheckInstStatus_CIS_IMPLICATED.String(),
},
{
Rank: 2,
Target: 8,
Status: chk.CheckInstStatus_CIS_STOPPED.String(),
},
{
Rank: 1,
Target: 9,
Status: chk.CheckInstStatus_CIS_COMPLETED.String(),
},
},
},
"pool-5": {
UUID: "pool-5",
Status: chkpb.CheckPoolStatus_CPS_UNCHECKED.String(),
Phase: chkpb.CheckScanPhase_CSP_PREPARE.String(),
Targets: []*control.SystemCheckTargetInfo{
{
Rank: 1,
Target: 10,
Status: chk.CheckInstStatus_CIS_RUNNING.String(),
},
{
Rank: 1,
Target: 11,
Status: chk.CheckInstStatus_CIS_PAUSED.String(),
},
{
Rank: 1,
Target: 12,
Status: chk.CheckInstStatus_CIS_RUNNING.String(),
},
},
},
},
Reports: []*control.SystemCheckReport{
Expand All @@ -108,6 +173,8 @@ No reports to display.
Action: chkpb.CheckInconsistAction_CIA_IGNORE,
Msg: "message 1",
PoolUuid: "pool-1",
Rank: 2,
Target: 0,
},
},
{
Expand All @@ -117,6 +184,7 @@ No reports to display.
Action: chkpb.CheckInconsistAction_CIA_TRUST_MS,
Msg: "message 2",
PoolUuid: "pool-2",
Rank: uint32(ranklist.NilRank),
},
},
{
Expand All @@ -126,6 +194,8 @@ No reports to display.
Action: chkpb.CheckInconsistAction_CIA_TRUST_PS,
Msg: "message 3",
PoolUuid: "pool-3",
Rank: 2,
Target: 4,
},
},
{
Expand All @@ -149,14 +219,32 @@ DAOS System Checker Info

Per-Pool Checker Info:
Pool pool-1: 0 ranks, status: CPS_CHECKED, phase: CSP_DONE, started: 2023-03-20T10:07:00.000-05:00
Rank 0 target status:
CIS_COMPLETED: [2]
CIS_FAILED: [1]
Rank 1 target status:
CIS_COMPLETED: [3]
Pool pool-2: 0 ranks, status: CPS_CHECKED, phase: CSP_DONE, started: 2023-03-20T10:07:00.000-05:00
Rank 0 target status:
CIS_COMPLETED: [4-6]
Pool pool-3: 0 ranks, status: CPS_CHECKED, phase: CSP_DONE, started: 2023-03-20T10:07:00.000-05:00
Rank 1 target status:
CIS_COMPLETED: [9]
Rank 2 target status:
CIS_STOPPED: [8]
Rank 3 target status:
CIS_IMPLICATED: [7]
Pool pool-5: 0 ranks, status: CPS_UNCHECKED, phase: CSP_PREPARE
Rank 1 target status:
CIS_PAUSED: [11]
CIS_RUNNING: [10,12]

Inconsistency Reports:
ID: 0x1
Class: POOL_BAD_SVCL
Message: message 1
Rank: 2
Target: 0
Pool: pool-1
Resolution: IGNORE

Expand All @@ -169,12 +257,16 @@ Inconsistency Reports:
ID: 0x3
Class: POOL_LESS_SVC_WITHOUT_QUORUM
Message: message 3
Rank: 2
Target: 4
Pool: pool-3
Resolution: TRUST_PS

ID: 0x4
Class: POOL_NONEXIST_ON_ENGINE
Message: message 4
Rank: 0
Target: 0
Pool: pool-4
Resolution: DISCARD (dry run - not applied)

Expand Down Expand Up @@ -595,6 +687,8 @@ Inconsistency Reports:
ID: 0x1
Class: POOL_BAD_LABEL
Message: message 1
Rank: 0
Target: 0
Pool: pool-1
Potential resolution actions:
0: trust MS details
Expand Down
Loading
Loading