Skip to content

Commit 57ec56b

Browse files
authored
HDDS-14775. Check leader status before serving bootstrap request. (#9873)
1 parent 1bde5be commit 57ec56b

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import java.util.stream.Stream;
5555
import javax.servlet.ServletException;
5656
import javax.servlet.http.HttpServletRequest;
57+
import javax.servlet.http.HttpServletResponse;
5758
import org.apache.commons.compress.archivers.ArchiveOutputStream;
5859
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
5960
import org.apache.commons.io.FileUtils;
@@ -133,6 +134,26 @@ public void init() throws ServletException {
133134
lock = new Lock(om);
134135
}
135136

137+
@Override
138+
public void processMetadataSnapshotRequest(HttpServletRequest request, HttpServletResponse response,
139+
boolean isFormData, boolean flush) {
140+
OzoneManager om = (OzoneManager) getServletContext().getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE);
141+
boolean isOmLeader = om.isLeaderReady();
142+
if (!isOmLeader) {
143+
String msg = "Unable to process metadata snapshot request as "
144+
+ "this OM is not the leader or not ready to serve requests";
145+
LOG.warn(msg);
146+
try {
147+
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, msg);
148+
} catch (IOException e) {
149+
LOG.warn("Failed to send error response, falling back to status only", e);
150+
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
151+
}
152+
return;
153+
}
154+
super.processMetadataSnapshotRequest(request, response, isFormData, flush);
155+
}
156+
136157
@Override
137158
public void writeDbDataToStream(DBCheckpoint checkpoint,
138159
HttpServletRequest request,

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServletInodeBasedXfer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,20 @@ public BootstrapStateHandler.Lock getBootstrapStateLock() {
143143
@Override
144144
public void processMetadataSnapshotRequest(HttpServletRequest request, HttpServletResponse response,
145145
boolean isFormData, boolean flush) {
146+
OzoneManager om = (OzoneManager) getServletContext().getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE);
147+
boolean isOmLeader = om.isLeaderReady();
148+
if (!isOmLeader) {
149+
String msg = "Unable to process metadata snapshot request as "
150+
+ "this OM is not the leader or not ready to serve requests";
151+
LOG.warn(msg);
152+
try {
153+
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, msg);
154+
} catch (IOException e) {
155+
LOG.warn("Failed to send error response, falling back to status only", e);
156+
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
157+
}
158+
return;
159+
}
146160
String[] sstParam = isFormData ?
147161
parseFormDataParameters(request) : request.getParameterValues(
148162
OZONE_DB_CHECKPOINT_REQUEST_TO_EXCLUDE_SST);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.hadoop.ozone.om;
19+
20+
import static org.mockito.ArgumentMatchers.anyString;
21+
import static org.mockito.ArgumentMatchers.eq;
22+
import static org.mockito.Mockito.doReturn;
23+
import static org.mockito.Mockito.doThrow;
24+
import static org.mockito.Mockito.mock;
25+
import static org.mockito.Mockito.spy;
26+
import static org.mockito.Mockito.verify;
27+
import static org.mockito.Mockito.when;
28+
29+
import java.io.IOException;
30+
import javax.servlet.ServletContext;
31+
import javax.servlet.http.HttpServletRequest;
32+
import javax.servlet.http.HttpServletResponse;
33+
import org.apache.hadoop.ozone.OzoneConsts;
34+
import org.junit.jupiter.api.Test;
35+
36+
/**
37+
* Unit tests for {@link OMDBCheckpointServletInodeBasedXfer} behavior when this OM is not leader.
38+
*/
39+
class TestOMDBCheckpointServletInodeBasedXferNonLeader {
40+
41+
@Test
42+
void processMetadataSnapshotRequestReturns503WhenNotLeader() throws Exception {
43+
OMDBCheckpointServletInodeBasedXfer servlet =
44+
spy(new OMDBCheckpointServletInodeBasedXfer());
45+
OzoneManager om = mock(OzoneManager.class);
46+
when(om.isLeaderReady()).thenReturn(false);
47+
48+
ServletContext ctx = mock(ServletContext.class);
49+
when(ctx.getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE)).thenReturn(om);
50+
doReturn(ctx).when(servlet).getServletContext();
51+
52+
HttpServletRequest request = mock(HttpServletRequest.class);
53+
HttpServletResponse response = mock(HttpServletResponse.class);
54+
55+
servlet.processMetadataSnapshotRequest(request, response, false, true);
56+
57+
verify(response).sendError(eq(HttpServletResponse.SC_SERVICE_UNAVAILABLE), anyString());
58+
}
59+
60+
@Test
61+
void processMetadataSnapshotRequestSetsStatusWhenSendErrorFails() throws Exception {
62+
OMDBCheckpointServletInodeBasedXfer servlet =
63+
spy(new OMDBCheckpointServletInodeBasedXfer());
64+
OzoneManager om = mock(OzoneManager.class);
65+
when(om.isLeaderReady()).thenReturn(false);
66+
67+
ServletContext ctx = mock(ServletContext.class);
68+
when(ctx.getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE)).thenReturn(om);
69+
doReturn(ctx).when(servlet).getServletContext();
70+
71+
HttpServletRequest request = mock(HttpServletRequest.class);
72+
HttpServletResponse response = mock(HttpServletResponse.class);
73+
doThrow(new IOException("broken pipe")).when(response)
74+
.sendError(eq(HttpServletResponse.SC_SERVICE_UNAVAILABLE), anyString());
75+
76+
servlet.processMetadataSnapshotRequest(request, response, false, true);
77+
78+
verify(response).setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
79+
}
80+
}

0 commit comments

Comments
 (0)