PR 1105: show the data layout and shards of V2 sharded volumes
longhorn/longhorn-ui · our PR · reviewed at 13cc3ba (base 0f560ca) · 11 November 2026 · two passes: Cody's process (ai-skills 679c21e) and ours
Preview: http://13.60.211.184:30084 · built from 13cc3ba, backend Longhorn master-head with V2 sharding (our dev cluster). Test volumes: ec-ui (sharded 2+1), nrq-test (V2 replicated), pvc-067104e7… (V1).
Verdict: ready for maintainers after a few small changes (both passes)
No blockers. The Shards card, the Volume Details rows, the Data Layout column, the websocket and the replicated volumes all behave as the description says, on both passes and against master.
One thing misleads: the count column still says "(Running/Desired)", but for sharded volumes it counts healthy shards. A detached sharded volume reads "3 / 3 shards" next to a detached replicated volume reading "0 / 2" (checked live by detaching ec-ui).
Also: the new Data tag fails text contrast (2.95:1), the failure time is only on hover, an unused loading prop, and no tests for the helpers (optional). Separately from the code, the clip in the PR description shows the dev cluster's address in its URL band.
Test it yourself
Open ec-ui on master and on the PR: an empty Replicas card becomes a Shards card with three tiles, and Volume Details gets the Data Layout, Data Chunks, Parity Chunks and Strip Size rows.
Open the volume list. Data Layout is on by default. Turn on "Replicas / Shards" with Custom Column to see "3 / 3 shards".
Open nrq-test: a replicated volume keeps its Replicas card and now says "Data Layout: Replicated".
Please don't detach, delete or change the test volumes. Failed and rebuilding shards were shown by rewriting the shard data in the browser.
How the two passes compare
Cody's process
Ours
Verdict
Comment: 4 line comments, acceptance 5 met and 1 partly met (AC5)
The count column counts healthy shards under "Running/Desired" (Cody's checked the detached case live; ours raised the rebuilding case and asked about detached) · the failure time and the other shard details are mouse-only · the tile colours copy the Replica tile's low contrast
Only one pass
Data tag contrast 2.95:1 (a colour this PR picked) · the PR clip shows the dev cluster's address · acceptance table · demo · default table width and Create Volume checked
Unused loading prop, with the blank card and "0 / 3 shards" while shards load (Cody's dropped it as a nit) · no tests for the helpers (proved correct with a scratch test) · the "Node redundancy" filter never matches sharded volumes (on master too) · sort, column picker and header wrap at 1280 checked
Disagreed
The tile colours: Cody's keeps them ("made worse": the PR copies master's contrast to a new place); ours leaves them out (same colours as master's Replica tile). I'd leave them for a follow-up on both tiles, as on earlier reviews.
Dropped in the merge
Nothing. Every finding held when I re-checked it at 13cc3ba and on the previews.
Cost
This session: code-only steps while ours ran, browser steps after it
Fresh agent: ~11 min, 195k tokens, 53 tool calls
Order: ours ran first as a fresh agent that never saw Cody's pass. Cody's code-only steps ran meanwhile, and its candidate list (the detached count) was written before ours reported. Its browser checks, including the detach, ran after ours finished and before I read its results.
Findings, merged
1
The count column means two things: running replicas, but healthy shards
src/routes/volume/VolumeList.js:494, :500
Cody'sOurs
Suggestion
The header says "Replicas / Shards (Running/Desired)". Replicas count when running; shards count when state === 'normal'. A shard has no running state at all (the API object has state, role and rebuild progress only), and a detach keeps the shards normal. So:
Detached: a sharded volume reads "3 / 3 shards" while a detached replicated volume reads "0 / 2". Live: ec-ui detached through the API, then reattached; engine running again.
Rebuilding: a rebuilding replica counts as running, so a replicated volume reads "3 / 3"; a sharded volume with a shard being replaced reads "2 / 3 shards". Live, shard data rewritten in the browser.
Keep counting healthy shards, since that's what the API has, and let the cell say so: "3 / 3 healthy shards". The header can't describe both, so the cell carries the meaning. One word, no new logic. The other way, hiding the count when the volume is detached, would be the UI inventing a state the API doesn't report.
2
The Data tag's text is 2.95:1
src/components/Shard/Shard.js:16, :62
Cody's
Suggestion
antd's preset blue tag draws #1890ff text on #e6f7ff at 12px: 2.95:1, under the 4.5:1 of WCAG 1.4.3. The Parity tag (purple) is 6.26:1. Measured from computed styles on ec-ui's page. This is a colour the PR picked: master uses no preset tag colours anywhere.
The role tags, enlarged
Simplest fix
Another preset for Data: geekblue (#2f54eb on #f0f5ff) is about 5.3:1 by calculation and still reads as blue next to the purple Parity tag.
3
When a shard failed is only shown on hover
src/components/Shard/Shard.js:25-27 (also :40 and :57)
Cody'sOurs
Optional
"Failed 5 minutes ago" is a tooltip on plain text, and nothing in the Shards card takes focus (0 stops in 80 Tab presses), so keyboard and screen-reader users can't read it (WCAG 2.1.1). The full shard name and disk UUID tooltips work the same way, like the Replica tile on master. The failure time is the one that's new information.
Simulated failed and rebuilding shards, hovering "Failed"
Simplest fix
Put the time in the tile text ("Failed 5 minutes ago") instead of a tooltip. Where it goes in the tile is the designer's call.
The Spin never spins, so until /v1/shards answers the Shards card is blank and the list shows "0 / 3 shards" next to a Healthy volume. Live: shards request delayed 12 s. On a healthy backend that's as long as one request. ReplicaList on master has the same unused prop.
Simplest fix
Drop the prop and the Spin. Passing the model's loading flag would only matter on a slow backend.
5
No tests for the three new helpers
src/routes/volume/helper/index.js:782-796
Ours
Optional
isShardedVolume, getDataLayoutText and getVolumeShards are pure and every new view uses them. A scratch test (empty type is "Replicated", "Sharded 2+1", slot order 0, 2, 10, no prefix match, store array not mutated) passed 3/3, so they're right. The repo has only one test file, so this is optional.
6
The clip in the PR description shows the dev cluster's address
PR description, Test Result
Cody's
Your call
The URL band under the clip reads http://13.60.211.184:30084/#/volume/ec-ui. That's the dev cluster's public IP, and the Longhorn UI and API there have no login. PR 1104's clip was cropped before upload; this one wasn't. A cropped copy is ready (1280×780, ends at the Longhorn footer, the clip below). Swapping it removes the address from the description, but GitHub keeps the old description in its edit history and the old file stays reachable at its link.
Not changing in this PR
What
Why
Tile colours: white on #108eb9 is 3.76:1, on yellow 1.66:1, on red 3.44:1; gray labels 3.95:1
Same colours as master's Replica tile, so the two tiles match. Worth one follow-up for both.
Replica actions (Update Replicas Count…) and the Node page's disk replica count
Already listed in the PR description as not in this PR.
The "Node redundancy" search filter reads replicas, so it never matches a sharded volume
src/utils/filter.js is unchanged by the PR; same on master.
Checked, nothing to raise
What
Result
How
Shards websocket
Opens and closes as it should
Opens on /volume, stays open on /volume/ec-ui and between volumes, closes on /node and /dashboard, reopens on /volume (both passes)
Stale shard data between volumes
None
Hash navigation ec-ui → nrq-test → V1 in one session (ours)
Create Volume has no layout, shard, parity or chunk field (Cody's)
Default columns
No new overflow
The table already scrolls sideways on master at 1280, 1440 and 1920 (1910px); the PR makes it 2070px (Cody's). Header wraps to two readable lines at 1280 (ours)
Sorting by Data Layout, column picker
Fine
Replicated before Sharded and back; sorter saved like the others; picker lists both new labels (ours)
Errors
None
No console or page errors on either build; a failed shards request toasts and keeps the old data, like every model (ours)
Lint, tests, CI
Pass
eslint on the 15 changed files; jest (the repo's one suite); DCO, codespell, commit-lint green. Only RestoreBackupModal.js fails full-repo lint, on master too
Simpler shape, reused components, design
Nothing in scope
Shard and ShardList follow Replica and ReplicaList; making Replica render shards would add a mode through most of it. No design in the thread (Cody's)
Cody's process: demo and acceptance
Master, then the PR (the cropped copy of the PR description's clip).
Criterion (source)
Verdict
How
AC1
No layout configuration in the UI (derekbit, innobead: "display ... rather than configuration")
Met
Create Volume fields; the diff adds no action
AC2
The disk each shard is on (innobead: "showing disks for sharding")
Met
Node and disk path per tile, disk UUID on hover
AC3
Data vs parity shards (innobead: "data shard, parity")
Met
Data, Data, Parity tags
AC4
Failed and replacing shards look different (issue body: UI for 1061)
Met
Simulated in the browser; not seen with a real failure
AC5
Nothing misrepresents a sharded volume as replicated (issue body)
Partly met
Empty Replicas card and "0 / 1" are gone; the count's "Running" header (finding 1)
AC6
Replicated volumes unchanged (implied)
Met
V1 pvc and V2 nrq-test on both builds
Open questions, not gaps: "showing disks for sharding" could also mean the Node page's disk view; and backend 1061 calls sharding "Experimental", but nobody asked the UI to say so.
What I'd change before maintainers look
Count cell → "3 / 3 healthy shards" (finding 1).
Data tag → geekblue (finding 2).
Failure time in the tile text instead of a tooltip (finding 3), if you agree it belongs there.
Drop ShardList's unused loading prop and Spin (finding 4).
Tests for the three helpers (finding 5), optional.
PR description: swap in the cropped clip, and update the Test Result text for whatever above changes (finding 6).
One follow-up commit, then redeploy :30084, recheck and refresh the UI-changes page. Nothing is posted to GitHub until you say so.