Skip to content

fix: one unhealthy drive no longer fails its controller's inventory - #107

Merged
g-carre merged 5 commits into
test/ARTESCA-17960-disk-failure-scenario-gherkinfrom
fix/ARTESCA-17960-unhealthy-drive-inventory
Oct 23, 2026
Merged

g-carre merged 5 commits into
test/ARTESCA-17960-disk-failure-scenario-gherkinfrom
fix/ARTESCA-17960-unhealthy-drive-inventory

Conversation

@g-carre

@g-carre g-carre commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Commits, one per adapter fix: megaraid, ssacli, storcli2 drives, storcli2 volumes, then the storcli2 wait for a new volume on the host, with a SCSI rescan.

Fixes ARTESCA-17960 (RD-2154). Stacked on #105: it targets #105's branch, so the diff only shows the fix. Retarget it to main once #105 is merged.It supersedes #91.

Problem

One unhealthy drive could fail the inventory of its whole controller, so every healthy drive on that controller lost its device paths. On the RD-2154 node this blanked all disks in the UI.

Fixes

  • megaraid (the RD-2154 case). When the drive of a single-drive RAID0 volume fails, the volume goes offline (OfLn) and is no longer a block device. getPaths still tried to resolve its paths, failed, and failed LogicalVolumes for the whole controller.
    • An offline or failed volume (OfLn, Fail) now gets empty paths without error, whatever its Exposed to OS says. No storcli output was ever captured while a drive was failed (RD-2154 only has the error log), so storcli may still report the volume exposed; with Yes kept, the MegaRAID scenario gives the RD-2154 error again without this check.
    • A volume reported Exposed to OS: No also gets empty paths without error. Only this explicit value (spaces trimmed) skips resolution, since older storcli versions may not report the field.
    • OfLn is now reported Failed instead of Unknown.
  • megaraid JBOD drives. A JBOD drive whose by-id link or device node is missing, such as a failed or pulled drive, is kept with empty paths instead of failing the listing of every drive on the controller. Any other failure is still an error. physicaldrive.IsPathMissing holds the rule, and the storcli2 getter uses it too.
  • ssacli (from fix: a single failed drive no longer blanks a controller's device paths #91). A failed or pulled drive whose /dev node is gone made the lsblk lookup fail, which aborted the whole inventory. When the device node is gone, a lookup failure now marks the device's usage as unknown instead. Any other lookup failure, such as lsblk missing or failing on a device that exists, is still an error, so it cannot silently blank every drive. A free drive whose usage is unknown is reported Unknown, never UnassignedGood, so a drive that may carry data is never offered for a new volume.
  • storcli2 drives (from fix: a single failed drive no longer blanks a controller's device paths #91). A Used JBOD drive whose by-id link or device node is missing is kept with empty paths instead of failing the whole inventory. Any other resolution failure, such as a permission error, is still an error.
  • storcli2 volumes. The storcli2 scenario of fix: one unhealthy drive no longer fails its controller's inventory, with hardware scenarios #105 found that the offline volume of a failed drive was still reported with a permanent path built from its NAA Id, although it has no block device. An offline or failed volume, whatever its Exposed to OS says, or a volume reported Exposed to OS: No, now has no paths: neither the permanent path built from its NAA Id, nor a device path from a possibly stale OS drive name.
  • Volume creation. It still waits for the new volume: a volume listed before it is exposed to the OS has no paths yet, so it is treated as not settled, and creation keeps rescanning and retrying.
    • megaraid: a volume without paths no longer stops the search, so the offline volume of a failed drive still listing a requested slot cannot hide the new, exposed volume.
    • storcli2: CreateLV used to return a new volume with an NAA-based path even before it was exposed. It now waits, like megaraid and with the same SCSI rescan between checks (on mpi3mr hosts), until the volume is a block device of the host or NewVolumeSettleTimeout (60 s, also when left at zero) elapses. As in megaraid, the volume is settled only once its by-id link (or its device node, when storcli2 reports no NAA Id) exists on the host: storcli2 may report it exposed right after add vd, before the kernel has discovered it. An offline volume with the same drives cannot hide the new one.
  • DESIGN.md. Documents the contract that getter read paths degrade gracefully, which failures still are errors, and that the megaraid and storcli2 create paths are deliberately stricter.

#91's change for multi-drive megaraid volumes is not carried over, since ARTESCA does not use them.

Tests

  • Scenarios. In megaraid-disk-failure.feature and storcli2-disk-failure.feature, the scenario "A failed drive does not take the paths of the others" now reports its expected table, so both known bug ARTESCA-17960 reports instead: steps are removed. Until they were removed, those steps failed with "the bug looks fixed". All 12 scenarios pass (4 per controller), for example on MegaRAID:
    --- PASS: TestScenarios/All_drives_are_healthy
    --- PASS: TestScenarios/A_failed_drive_does_not_take_the_paths_of_the_others
    --- PASS: TestScenarios/A_replacement_drive_is_reported_as_a_new,_available_drive
    --- PASS: TestScenarios/A_replacement_drive_gets_the_paths_of_its_new_volume
    
  • megaraid unit tests, table-driven:
    • getPaths with Exposed to OS set to No (empty paths, no error), Yes, or empty (paths still resolved);
    • volumePaths: an OfLn or Fail volume reported exposed gets empty paths and no error, an Optl or Dgrd one still has its paths resolved;
    • the volume status mapping, including OfLn → Failed;
    • the new volume selection: an offline volume sharing a slot, listed before or after the new volume, does not hide it.
  • Volume creation: a new volume first listed as not exposed must be awaited, not returned without paths.
  • ssacli: a failing lsblk lookup does not abort the inventory when the device node is gone, and is still an error when it exists. A free drive whose device could not be inspected is reported Unknown.
  • storcli2, from fix: a single failed drive no longer blanks a controller's device paths #91: an unresolvable JBOD drive, and a degraded storcli2 RAID volume. New: an offline or failed volume gets no paths even when reported exposed (volumePaths), a volume not exposed to the OS gets none either, and byIDPath (formerly permanentPath) covers Exposed to OS set to No, Yes and missing. CreateLV waits for a volume exposed on the third listing, gives up on one never exposed, is not hidden by an offline volume with the same drives listed first, and returns at once a volume exposed without an NAA Id.

Known risk

The storcli2 CreateLV wait has not run on storcli2 hardware: none is available at the moment. It waits for the new volume's path on the host and rescans the mpi3mr SCSI hosts between checks, as megaraid does, with the same sysfs write. If a new storcli2 volume still does not appear, CreateLV fails after 60 s, and the volume stays on the controller (MK8S-467).

Delivery

disk-management-agent picks this up once raidmgmt is released and the agent bumps it.

Comment thread pkg/implementation/raidcontroller/megaraid/logicalvolume.go Outdated
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 697914a to 4ee0286 Compare October 15, 2026 16:35
@g-carre
g-carre requested a review from a team as a code owner October 15, 2026 16:35
@g-carre
g-carre requested review from ezekiel-alexrod and riadelhajjaji-scality and removed request for a team October 15, 2026 16:35
@g-carre
g-carre force-pushed the test/ARTESCA-17960-disk-failure-scenario-gherkin branch from 74a8271 to eb4261b Compare October 15, 2026 16:35
Comment thread pkg/implementation/logicalvolumegetter/storcli2.go Outdated
blockDevice, err := s.getBlockDevice(value)
if err != nil {
return errors.Wrapf(err, "failed to get block device for %s", value)
facts.blockDeviceUnknown = true

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.

This drops every getBlockDevice error, not just a missing device node. If lsblk is missing, fails for another reason, or its JSON format changes, every drive silently loses its DevicePath and every free drive becomes Unknown, and nothing reports why. That is the "all disks blanked" symptom this PR fixes, now with no error at all. Only degrade when the node is actually gone (for example, check that value exists before calling lsblk), and keep returning the wrapped error otherwise.

@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 4ee0286 to 594d87d Compare October 15, 2026 16:44
Comment thread pkg/implementation/logicalvolumemanager/storcli2.go Outdated
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 594d87d to a1f75a3 Compare October 15, 2026 16:47
Comment thread pkg/implementation/logicalvolumemanager/storcli2.go Outdated
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch 2 times, most recently from dc6a89b to da9ef41 Compare October 15, 2026 21:21
@g-carre
g-carre force-pushed the test/ARTESCA-17960-disk-failure-scenario-gherkin branch 2 times, most recently from ae2f0cd to 3791dcd Compare October 15, 2026 21:37
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from da9ef41 to f943de8 Compare October 15, 2026 21:37
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from f943de8 to 0d51fda Compare October 16, 2026 12:36
@g-carre
g-carre force-pushed the test/ARTESCA-17960-disk-failure-scenario-gherkin branch 2 times, most recently from a7ab071 to 11b2a13 Compare October 16, 2026 12:50
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 0d51fda to 02850ad Compare October 16, 2026 12:50
@g-carre
g-carre requested a review from m4nch0t October 16, 2026 13:00
Comment thread pkg/implementation/logicalvolumemanager/storcli2.go
Comment thread pkg/implementation/raidcontroller/megaraid/logicalvolume.go

@riadelhajjaji-scality riadelhajjaji-scality left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You say in DESIGN.md that a JBOD drive whose by-id link can't be resolved is returned with empty paths. That s true for storcli2 (isPathMissing), but the legacy MegaRAID adapter still fails the whole PhysicalDrives() listing at raidcontroller/megaraid/physicaldrive.go:131. Should we apply the same fix for MegaRAID or scope the DESIGN.md sentence to storcli2 and ssacli ?

@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch 2 times, most recently from f9eec44 to 9673f89 Compare October 21, 2026 13:05
@g-carre

g-carre commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Good catch: the legacy MegaRAID adapter had the same problem, and it was worse, since it looks up the paths of every JBOD drive, failed ones included. A failed or pulled JBOD drive would blank every drive of the controller, which is the ARTESCA-17960 symptom. Our scenarios didn't catch it because the captures only have RAID0 volumes.

Fixed in 9673f89 rather than narrowing DESIGN.md, which is now true for all three adapters:

  • Shared check. physicaldrive.IsPathMissing(err) sits next to ErrNoPermanentPath. It is true for a missing by-id link, or a link to a device node that is gone. The storcli2 getter uses it in place of its own isPathMissing.
  • MegaRAID (megaraid/physicaldrive.go): a JBOD drive whose link or node is missing is kept with empty paths. Any other error, such as a permission error, still fails, as in storcli2.
  • Tests:
    • TestPhysicalDriveJBODWithoutLink: a JBOD drive in state JBOD or Failed with no by-id link is returned with empty paths. It fails without the fix ("failed to compute paths").
    • TestIsPathMissing covers the shared check.

The change is in the megaraid commit, and the storcli2 JBOD commit uses the shared check.

When the drive of a single-drive RAID0 volume fails, the volume goes offline
and is no longer a block device of the host: it has no by-id link, and the
paths of its failed drive cannot be computed. getPaths returned an error,
which failed LogicalVolumes for the whole controller, so the healthy drives
of that controller lost their paths too (RD-2154).

- An offline or failed volume (OfLn, Fail) gets empty paths without error,
  whatever its "Exposed to OS" says: no storcli output was captured while
  a drive was failed, so storcli may still report the volume exposed.
- A volume whose "Exposed to OS" is "No" gets empty paths without error.
  Only this explicit value, spaces trimmed, skips the resolution, as older
  storcli versions may not report the field.
- An offline volume (OfLn) is reported Failed instead of Unknown.
- A JBOD drive whose by-id link or device node is missing, such as a
  failed or pulled drive, is kept with empty paths instead of failing the
  listing of every drive of the controller. Any other failure, such as a
  permission error, is still an error. physicaldrive.IsPathMissing tells
  them apart, and ComputePaths now returns ErrNoPermanentPath for a
  missing link.
- Volume creation still waits for the new volume: a volume listed before it
  is exposed to the OS has no paths yet, so it is not settled and creation
  keeps rescanning and retrying. Such a volume no longer stops the search:
  the offline volume of a failed drive still listing a requested slot must
  not hide the new, exposed volume.

DESIGN.md states that getter read paths degrade gracefully while the create
path stays strict. The failed drive scenario of megaraid-disk-failure.feature
now reports its expected table: its known bug step is removed.

Fixes: ARTESCA-17960
A failed or pulled drive whose device node has disappeared made the lsblk
lookup of its Disk Name fail, which aborted the physical drive inventory of
the whole controller. The lookup only refines the status, so when it fails
and the device node is gone, it no longer aborts the inventory. Instead:

- the usage of the device is unknown, and a free drive whose usage is
  unknown is reported Unknown, never UnassignedGood, so a drive that may
  carry data is never offered for a new volume;
- the device path is dropped, as the kernel can reuse a vanished /dev/sdX
  name for another disk.

Array members and failed drives keep the status ssacli reports. A lookup
failure on a device that exists, such as lsblk missing or its output
changing, is still an error: ignoring it would silently blank every drive.

Refs: ARTESCA-17960
… resolved

A JBOD drive whose by-id link cannot be resolved, for instance because udev
has not settled yet, failed the physical drive inventory of the whole
controller. Keep it with empty paths instead, when its by-id link or device
node is missing (physicaldrive.IsPathMissing, as for MegaRAID). Any other
failure, such as a permission error, is still an error: ignoring it would
silently blank the paths of every JBOD drive. Also cover a degraded RAID
volume, whose paths come from the controller output only.

Refs: ARTESCA-17960
The storcli2 volume getter read the device path of a volume from its OS
drive name and built its permanent path from its NAA Id. The offline RAID0
volume of a failed drive keeps its NAA Id, and may keep a stale OS drive
name, but it is not exposed to the OS: it has no block device and no by-id
link, so both paths named nothing, or another disk. A volume whose "Exposed
to OS" is "No" now has no paths; only this explicit value drops them, as
older storcli2 versions may not report the field. An offline or failed
volume (OfLn, Fail) has no paths either, whatever its "Exposed to OS" says,
as no storcli2 output was captured while a drive was failed.

Volume creation used to get the NAA-based path of a new volume listed
before it is exposed to the OS. It now gets no paths, so CreateLV waits,
like megaraid, until the new volume is exposed or NewVolumeSettleTimeout
elapses (60s when zero). DESIGN.md says which failures degrade and which stay errors.

The failed drive scenario of storcli2-disk-failure.feature now reports its
expected table: its known bug step is removed.

Fixes: ARTESCA-17960
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 129b5d0 to 450b359 Compare October 21, 2026 14:43
@g-carre
g-carre force-pushed the test/ARTESCA-17960-disk-failure-scenario-gherkin branch from 11b2a13 to 8476ff8 Compare October 21, 2026 14:44
Comment thread pkg/implementation/logicalvolumemanager/storcli2.go Outdated

@ezekiel-alexrod ezekiel-alexrod left a comment

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.

See the above claude review comment

… hosts

CreateLV waits for a new storcli2 volume to be exposed to the OS, but did
not rescan the SCSI bus between checks as megaraid does. If the kernel does
not announce the new volume on its own, CreateLV failed after 60s and left
the volume on the controller. This wait never ran on storcli2 hardware.

- The rescan of megaraid moves to utils.RescanSCSIHosts, which takes the
  kernel driver of the hosts to rescan, so both adapters share it.
- The storcli2 wait rescans the mpi3mr hosts, the driver of the
  controllers storcli2 drives (MegaRAID 9600 tri-mode, Dell PERC 12),
  between checks. A rescan failure is not fatal on its own, but it is
  reported on timeout, as in megaraid.
- A new volume is settled only once its by-id link, or its device node
  when storcli2 reports no NAA Id, exists on the host, as megaraid checks
  it. storcli2 may report the volume exposed, with its paths, right after
  "add vd", before the kernel has discovered it: the wait and the rescan
  would then never run.
- StorCLI2.RescanSCSIHosts and StorCLI2.FileExists replace the rescan and
  the host check in tests; nil rescans the mpi3mr hosts and reads the
  filesystem.

Refs: ARTESCA-17960
@g-carre
g-carre force-pushed the fix/ARTESCA-17960-unhealthy-drive-inventory branch from 450b359 to 38041bd Compare October 22, 2026 16:29
@riadelhajjaji-scality

Copy link
Copy Markdown

LGTM! Just waiting on Claude's comment

@g-carre
g-carre merged commit 7ffc169 into test/ARTESCA-17960-disk-failure-scenario-gherkin Oct 23, 2026
11 checks passed
@g-carre
g-carre deleted the fix/ARTESCA-17960-unhealthy-drive-inventory branch October 23, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants