This is an automated email from the ASF dual-hosted git repository. shenwenbing pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/master by this push: new 1d9e35dc1f Prevent bookie shutdown due to rest api when bookie prohibits readOnlyMode (#3972) 1d9e35dc1f is described below commit 1d9e35dc1f27af8e615e16e5e4a8ef979382e013 Author: wenbingshen <oliver.shen...@gmail.com> AuthorDate: Mon Apr 29 11:13:34 2024 +0800 Prevent bookie shutdown due to rest api when bookie prohibits readOnlyMode (#3972) --- .../bookkeeper/bookie/BookieStateManager.java | 5 +++ .../org/apache/bookkeeper/bookie/StateManager.java | 5 +++ .../http/service/BookieStateReadOnlyService.java | 5 +++ .../bookkeeper/server/http/TestHttpService.java | 40 +++++++++++++++++++--- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieStateManager.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieStateManager.java index 6f029e6782..9800d9e063 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieStateManager.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieStateManager.java @@ -235,6 +235,11 @@ public class BookieStateManager implements StateManager { return forceReadOnly.get(); } + @Override + public boolean isReadOnlyModeEnabled() { + return conf.isReadOnlyModeEnabled(); + } + @Override public boolean isAvailableForHighPriorityWrites() { return availableForHighPriorityWrites; diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/StateManager.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/StateManager.java index d279893a8a..7ed3f0b657 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/StateManager.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/StateManager.java @@ -53,6 +53,11 @@ public interface StateManager extends AutoCloseable { */ boolean isForceReadOnly(); + /** + * Check is readOnlyModeEnabled. + */ + boolean isReadOnlyModeEnabled(); + /** * Check is Running. */ diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/BookieStateReadOnlyService.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/BookieStateReadOnlyService.java index 23211d5218..d32074e2bb 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/BookieStateReadOnlyService.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/server/http/service/BookieStateReadOnlyService.java @@ -60,6 +60,11 @@ public class BookieStateReadOnlyService implements HttpEndpointService { } stateManager.transitionToWritableMode().get(); } else if (!stateManager.isReadOnly() && inState.isReadOnly()) { + if (!stateManager.isReadOnlyModeEnabled()) { + response.setCode(HttpServer.StatusCode.BAD_REQUEST); + response.setBody("Bookie is disabled ReadOnly mode, cannot transit to readOnly mode"); + return response; + } stateManager.transitionToReadOnlyMode().get(); } } else if (!HttpServer.Method.GET.equals(request.getMethod())) { diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java index 847c1118f5..2ea869e9da 100644 --- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java +++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/server/http/TestHttpService.java @@ -1023,11 +1023,43 @@ public class TestHttpService extends BookKeeperClusterTestCase { assertFalse(readOnlyState.isReadOnly()); //forceReadonly to writable - baseConf.setForceReadOnlyBookie(true); - baseConf.setReadOnlyModeEnabled(true); - restartBookies(); + MetadataBookieDriver metadataDriver = BookieResources.createMetadataDriver( + baseConf, NullStatsLogger.INSTANCE); + restartBookies(c -> { + c.setForceReadOnlyBookie(true); + c.setReadOnlyModeEnabled(true); + return c; + }); + // the old bkHttpServiceProvider has an old bookie instance who has been shutdown + // so we need create a new bkHttpServiceProvider2 to contains a new bookie which has created by restart. + BKHttpServiceProvider bkHttpServiceProvider2 = new BKHttpServiceProvider.Builder() + .setBookieServer(serverByIndex(numberOfBookies - 1)) + .setServerConfiguration(baseConf) + .setLedgerManagerFactory(metadataDriver.getLedgerManagerFactory()) + .build(); + HttpEndpointService bookieReadOnlyService2 = bkHttpServiceProvider2 + .provideHttpEndpointService(HttpServer.ApiType.BOOKIE_STATE_READONLY); + request = new HttpServiceRequest(JsonUtil.toJson(new ReadOnlyState(false)), HttpServer.Method.PUT, null); - response = bookieReadOnlyService.handle(request); + response = bookieReadOnlyService2.handle(request); + assertEquals(400, response.getStatusCode()); + + // disable readOnly mode + restartBookies(c -> { + c.setForceReadOnlyBookie(false); + c.setReadOnlyModeEnabled(false); + return c; + }); + bkHttpServiceProvider2 = new BKHttpServiceProvider.Builder() + .setBookieServer(serverByIndex(numberOfBookies - 1)) + .setServerConfiguration(baseConf) + .setLedgerManagerFactory(metadataDriver.getLedgerManagerFactory()) + .build(); + bookieReadOnlyService2 = bkHttpServiceProvider2 + .provideHttpEndpointService(HttpServer.ApiType.BOOKIE_STATE_READONLY); + + request = new HttpServiceRequest(JsonUtil.toJson(new ReadOnlyState(true)), HttpServer.Method.PUT, null); + response = bookieReadOnlyService2.handle(request); assertEquals(400, response.getStatusCode()); }