|
18 | 18 | import org.opensearch.common.settings.Settings;
|
19 | 19 | import org.opensearch.common.unit.TimeValue;
|
20 | 20 | import org.opensearch.index.query.QueryBuilders;
|
| 21 | +import org.opensearch.indices.recovery.PeerRecoveryTargetService; |
21 | 22 | import org.opensearch.indices.recovery.RecoverySettings;
|
22 | 23 | import org.opensearch.plugins.Plugin;
|
23 | 24 | import org.opensearch.test.OpenSearchIntegTestCase;
|
24 | 25 | import org.opensearch.test.hamcrest.OpenSearchAssertions;
|
25 | 26 | import org.opensearch.test.transport.MockTransportService;
|
| 27 | +import org.opensearch.transport.TransportService; |
26 | 28 | import org.opensearch.transport.client.Client;
|
27 | 29 | import org.opensearch.transport.client.Requests;
|
28 | 30 |
|
| 31 | +import java.io.IOException; |
29 | 32 | import java.util.Collection;
|
30 | 33 | import java.util.List;
|
31 | 34 | import java.util.concurrent.atomic.AtomicBoolean;
|
@@ -195,4 +198,87 @@ public void testMixedModeRelocation_RemoteSeedingFail() throws Exception {
|
195 | 198 | .setTransientSettings(Settings.builder().put(RecoverySettings.INDICES_INTERNAL_REMOTE_UPLOAD_TIMEOUT.getKey(), (String) null))
|
196 | 199 | .get();
|
197 | 200 | }
|
| 201 | + |
| 202 | + public void testMixedModeRelocation_FailInFinalize() throws Exception { |
| 203 | + String docRepNode = internalCluster().startNode(); |
| 204 | + ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest(); |
| 205 | + updateSettingsRequest.persistentSettings(Settings.builder().put(REMOTE_STORE_COMPATIBILITY_MODE_SETTING.getKey(), "mixed")); |
| 206 | + assertAcked(client().admin().cluster().updateSettings(updateSettingsRequest).actionGet()); |
| 207 | + |
| 208 | + // create shard with 0 replica and 1 shard |
| 209 | + client().admin().indices().prepareCreate("test").setSettings(indexSettings()).setMapping("field", "type=text").get(); |
| 210 | + ensureGreen("test"); |
| 211 | + |
| 212 | + AsyncIndexingService asyncIndexingService = new AsyncIndexingService("test"); |
| 213 | + asyncIndexingService.startIndexing(); |
| 214 | + |
| 215 | + refresh("test"); |
| 216 | + |
| 217 | + // add remote node in mixed mode cluster |
| 218 | + setAddRemote(true); |
| 219 | + String remoteNode = internalCluster().startNode(); |
| 220 | + internalCluster().validateClusterFormed(); |
| 221 | + |
| 222 | + AtomicBoolean failFinalize = new AtomicBoolean(true); |
| 223 | + |
| 224 | + MockTransportService remoteNodeTransportService = (MockTransportService) internalCluster().getInstance( |
| 225 | + TransportService.class, |
| 226 | + remoteNode |
| 227 | + ); |
| 228 | + |
| 229 | + remoteNodeTransportService.addRequestHandlingBehavior( |
| 230 | + PeerRecoveryTargetService.Actions.FINALIZE, |
| 231 | + (handler, request, channel, task) -> { |
| 232 | + if (failFinalize.get()) { |
| 233 | + throw new IOException("Failing finalize"); |
| 234 | + } else { |
| 235 | + handler.messageReceived(request, channel, task); |
| 236 | + } |
| 237 | + } |
| 238 | + ); |
| 239 | + |
| 240 | + client().admin() |
| 241 | + .cluster() |
| 242 | + .prepareUpdateSettings() |
| 243 | + .setTransientSettings(Settings.builder().put(RecoverySettings.INDICES_INTERNAL_REMOTE_UPLOAD_TIMEOUT.getKey(), "40s")) |
| 244 | + .get(); |
| 245 | + |
| 246 | + // Change direction to remote store |
| 247 | + updateSettingsRequest.persistentSettings(Settings.builder().put(MIGRATION_DIRECTION_SETTING.getKey(), "remote_store")); |
| 248 | + assertAcked(client().admin().cluster().updateSettings(updateSettingsRequest).actionGet()); |
| 249 | + |
| 250 | + logger.info("--> relocating from {} to {} ", docRepNode, remoteNode); |
| 251 | + client().admin().cluster().prepareReroute().add(new MoveAllocationCommand("test", 0, docRepNode, remoteNode)).execute().actionGet(); |
| 252 | + ClusterHealthResponse clusterHealthResponse = client().admin() |
| 253 | + .cluster() |
| 254 | + .prepareHealth() |
| 255 | + .setTimeout(TimeValue.timeValueSeconds(5)) |
| 256 | + .setWaitForEvents(Priority.LANGUID) |
| 257 | + .setWaitForNoRelocatingShards(true) |
| 258 | + .execute() |
| 259 | + .actionGet(); |
| 260 | + |
| 261 | + assertTrue(clusterHealthResponse.getRelocatingShards() == 1); |
| 262 | + |
| 263 | + ClusterHealthRequest healthRequest = Requests.clusterHealthRequest() |
| 264 | + .waitForNoRelocatingShards(true) |
| 265 | + .waitForNoInitializingShards(true); |
| 266 | + ClusterHealthResponse actionGet = client().admin().cluster().health(healthRequest).actionGet(); |
| 267 | + assertEquals(actionGet.getRelocatingShards(), 0); |
| 268 | + assertEquals(docRepNode, primaryNodeName("test")); |
| 269 | + |
| 270 | + // now unblock it |
| 271 | + logger.info("Unblocking the finalize recovery now"); |
| 272 | + failFinalize.set(false); |
| 273 | + |
| 274 | + client().admin().cluster().prepareReroute().add(new MoveAllocationCommand("test", 0, docRepNode, remoteNode)).execute().actionGet(); |
| 275 | + waitForRelocation(); |
| 276 | + |
| 277 | + asyncIndexingService.stopIndexing(); |
| 278 | + client().admin() |
| 279 | + .cluster() |
| 280 | + .prepareUpdateSettings() |
| 281 | + .setTransientSettings(Settings.builder().put(RecoverySettings.INDICES_INTERNAL_REMOTE_UPLOAD_TIMEOUT.getKey(), (String) null)) |
| 282 | + .get(); |
| 283 | + } |
198 | 284 | }
|
0 commit comments