Siyao Meng created HDDS-17070:
---------------------------------
Summary: Recon does not follow container suppression changes made
in SCM after it has added the container
Key: HDDS-17070
URL: https://issues.apache.org/jira/browse/HDDS-17070
Project: Apache Ozone
Issue Type: Bug
Reporter: Siyao Meng
Attachments: CR-1-sync-suppressed-flag-from-scm.patch,
TestBugCR1SuppressedFlagNotRefreshed.java
h3. Mechanism
Container suppression (HDDS-14103) is set and cleared in SCM with {{ozone admin
container report --suppress}} / {{--unsuppress}}. HDDS-14103 states that Recon
can use it "to keep its missing container alerts in sync with SCM". Recon's
health sweep ({{ReconReplicationManager}}, through
{{ReplicationManager.processContainer}}) already skips suppressed containers,
using Recon's own copy of {{ContainerInfo}}.
Recon copies the flag from SCM only when it first adds a container or installs
a full SCM DB snapshot. The periodic sync
({{ReconStorageContainerSyncHelper.syncWithSCMContainerInfo}}, every 6 hours by
default) works from container IDs and lifecycle states only:
{{reconcileExistingContainer}} returns as soon as the states match, and never
compares the flag. A full snapshot happens only at startup, when the container
count drift exceeds {{ozone.recon.scm.container.threshold}} (default
1,000,000). HDDS-14103 changed no Recon code.
h3. Trigger
* An admin suppresses a container in SCM, typically a MISSING one, after Recon
has added it. This is the normal order, since Recon learns of a container when
it is created.
* The reverse: an admin unsuppresses a container that Recon added while SCM had
it suppressed (a new or rebuilt Recon, or a snapshot install).
h3. Impact
* A container suppressed in SCM stays unsuppressed in Recon, so Recon keeps
reporting it as MISSING (or under replicated) while {{ozone admin container
report}} hides it. This follows from the code above; the patch's tests cover it.
* A container unsuppressed in SCM stays suppressed in Recon, and Recon's health
sweep skips it. If it has lost all its replicas, Recon writes no MISSING row
for it. In the attached run, after a full successful periodic sync Recon still
had the container suppressed while SCM did not, and the sweep wrote a MISSING
row only for the other container, although both had no replica.
The divergence has no time limit in normal operation.
h3. Reproduction
[^TestBugCR1SuppressedFlagNotRefreshed.java] goes in {{hadoop-ozone/recon}}
(target path and Maven command in the class comment) and passes on unmodified
source when the bug is present. It uses a real {{ReconContainerManager}}, the
real sync helper and the real {{ReconReplicationManager}} health check chain.
Only the SCM RPC peer is mocked, returning what SCM returns after an
unsuppress, and the health schema manager is mocked to capture the rows the
sweep writes.
h3. Patch
[^CR-1-sync-suppressed-flag-from-scm.patch], against
916aa1d9949cbb10f2750a40c8704340893131a2. It also applies to master at
d77edaa6c15.
* The periodic sync gains one step: it pages through SCM's {{listContainer}}
with the existing suppressed filter, collects the suppressed IDs, then sets the
flag on every Recon container where it differs, in both directions. If the
listing fails, nothing is changed and the sync reports failure like the other
passes. An SCM that ignores the filter returns unsuppressed containers; since
the filter came with the flag, such an SCM has no suppressed containers, so the
step stops after the first page. The cost is one {{listContainer}} pass per
sync cycle; SCM evaluates the filter by scanning its container map.
* {{ReplicationManager.processContainer}} returns before it updates the health
state of a suppressed container, so a container that was MISSING when it was
suppressed kept that state in memory and Recon kept writing its MISSING row
until a restart. {{ReconReplicationManager.processAll}} now resets the health
state of a suppressed container to HEALTHY before that call, so no health row
is written for it. The shared {{processContainer}} and SCM are not changed.
Covered by three new cases in
{{TestReconSCMContainerSyncIntegration.SuppressedFlagSyncTests}} (flags copied
in both directions; one listing call against an SCM that ignores the filter;
flags unchanged when the listing fails) and by
{{TestReconReplicationManager.testProcessAllFollowsSuppressedFlag}} (a MISSING
container gets no row once suppressed and gets it back once unsuppressed).
Without the change the sync case fails on the first flag and the sweep case
still finds the MISSING row after suppression. With it the Recon {{scm}} and
{{fsck}} unit tests pass, checkstyle is clean, and the attached test no longer
shows the bug.
A failing health sweep also retries without waiting; that is a separate issue
with its own patch.
Found by code review of the datanode container report and Recon container
tracking paths, as part of the TLA+ verification effort under HDDS-15926, on
commit 916aa1d9949cbb10f2750a40c8704340893131a2. Checked against HDDS issues
and apache/ozone pull requests for duplicates before filing. Related but not
duplicates: HDDS-14103 (resolved, added container suppression), HDDS-13891
(resolved, the current Recon health task). The attached patch is a proposal for
review. Generated with Specula (Claude Opus 5.5).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]