diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java index 6fb479592ad1..cab9321937b2 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java @@ -118,6 +118,7 @@ public void postFinalizeUpgrade(SCMUpgradeFinalizationContext context) createPipelinesAfterFinalization(context); stateManager.removeFinalizingMark(); } + logCheckpointCrossed(FinalizationCheckpoint.FINALIZATION_COMPLETE); } private void closePipelinesBeforeFinalization(PipelineManager pipelineManager) diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmFinalization.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmFinalization.java index 67e661bc9d07..12fddb06b1a3 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmFinalization.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmFinalization.java @@ -19,9 +19,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.matches; @@ -31,6 +33,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.IOException; import java.util.Arrays; import java.util.UUID; import org.apache.hadoop.hdds.conf.OzoneConfiguration; @@ -53,6 +56,8 @@ import org.apache.hadoop.ozone.OzoneConsts; import org.apache.hadoop.ozone.upgrade.UpgradeFinalization; import org.apache.hadoop.ozone.upgrade.UpgradeFinalization.StatusAndMessages; +import org.apache.hadoop.ozone.upgrade.UpgradeFinalizer; +import org.apache.ozone.test.GenericTestUtils.LogCapturer; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -65,6 +70,8 @@ * Tests SCM finalization operations on mocked upgrade state. */ public class TestScmFinalization { + private static final String FINALIZATION_COMPLETE_LOG = + "SCM Finalization has crossed checkpoint FINALIZATION_COMPLETE"; private static final Logger LOG = LoggerFactory.getLogger(TestScmFinalization.class); @@ -231,8 +238,17 @@ public void testResumeFinalizationFromCheckpoint( // Execute upgrade finalization, then check that events happened in the // correct order. - StatusAndMessages status = - manager.finalizeUpgrade(UUID.randomUUID().toString()); + LogCapturer logCapturer = + LogCapturer.captureLogs(UpgradeFinalizer.class); + StatusAndMessages status; + try { + status = manager.finalizeUpgrade(UUID.randomUUID().toString()); + assertEquals( + initialCheckpoint != FinalizationCheckpoint.FINALIZATION_COMPLETE, + logCapturer.getOutput().contains(FINALIZATION_COMPLETE_LOG)); + } finally { + logCapturer.stopCapturing(); + } assertEquals(getStatusFromCheckpoint(initialCheckpoint).status(), status.status()); @@ -296,6 +312,36 @@ public void testResumeFinalizationFromCheckpoint( // have been invoked. } + @Test + public void testFinalizationCompleteNotLoggedWhenRemovingMarkFails() + throws Exception { + FinalizationStateManager stateManager = mock(FinalizationStateManager.class); + when(stateManager.crossedCheckpoint( + FinalizationCheckpoint.FINALIZATION_COMPLETE)).thenReturn(false); + doThrow(new IOException("Failed to remove finalizing mark")) + .when(stateManager).removeFinalizingMark(); + + SCMUpgradeFinalizationContext context = + mock(SCMUpgradeFinalizationContext.class); + PipelineManager pipelineManager = getMockPipelineManager( + FinalizationCheckpoint.MLV_EQUALS_SLV); + when(context.getFinalizationStateManager()).thenReturn(stateManager); + when(context.getPipelineManager()).thenReturn(pipelineManager); + when(context.getSCMContext()).thenReturn(SCMContext.emptyContext()); + + SCMUpgradeFinalizer finalizer = + new SCMUpgradeFinalizer(mock(HDDSLayoutVersionManager.class)); + LogCapturer logCapturer = LogCapturer.captureLogs(UpgradeFinalizer.class); + try { + IOException exception = assertThrows(IOException.class, + () -> finalizer.postFinalizeUpgrade(context)); + assertEquals("Failed to remove finalizing mark", exception.getMessage()); + assertFalse(logCapturer.getOutput().contains(FINALIZATION_COMPLETE_LOG)); + } finally { + logCapturer.stopCapturing(); + } + } + /** * On startup, the finalization table will be read to determine the * checkpoint we are resuming from. After this, the results will be stored