]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12187 make ES indices read-write at startup if are read-only
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 13 Jun 2019 07:19:48 +0000 (09:19 +0200)
committerSonarTech <sonartech@sonarsource.com>
Fri, 14 Jun 2019 18:21:10 +0000 (20:21 +0200)
server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java
server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java

index 4bee944bbfa5f1c74cfba95ee16e3624b4a4689b..0a45e823dbee4843fee9d93bc90c685e2b4e0d4b 100644 (file)
@@ -26,6 +26,8 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
+import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
+import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
 import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
 import org.elasticsearch.common.settings.Settings;
@@ -81,6 +83,8 @@ public class IndexCreator implements Startable {
       metadataIndexDefinition.define(context);
       NewIndex index = context.getIndices().values().iterator().next();
       createIndex(index.build(), false);
+    } else {
+      ensureWritable(metadataMainType);
     }
 
     checkDbCompatibility(definitions.getIndices().values());
@@ -94,10 +98,36 @@ public class IndexCreator implements Startable {
           createIndex(index, true);
         } else if (hasDefinitionChange(index)) {
           updateIndex(index);
+        } else {
+          ensureWritable(index.getMainType());
         }
       });
   }
 
+  private void ensureWritable(IndexType.IndexMainType mainType) {
+    if (isReadOnly(mainType)) {
+      removeReadOnly(mainType);
+    }
+  }
+
+  private boolean isReadOnly(IndexType.IndexMainType mainType) {
+    String indexName = mainType.getIndex().getName();
+    String readOnly = client.nativeClient().admin().indices().getSettings(new GetSettingsRequest().indices(indexName)).actionGet()
+      .getSetting(indexName, "index.blocks.read_only_allow_delete");
+    return readOnly != null && "true".equalsIgnoreCase(readOnly);
+  }
+
+  private void removeReadOnly(IndexType.IndexMainType mainType) {
+    LOGGER.info("Index [{}] is read-only. Making it writable...", mainType.getIndex().getName());
+
+    String indexName = mainType.getIndex().getName();
+    Settings.Builder builder = Settings.builder();
+    builder.putNull("index.blocks.read_only_allow_delete");
+    client.nativeClient().admin().indices()
+      .updateSettings(new UpdateSettingsRequest().indices(indexName).settings(builder.build()))
+      .actionGet();
+  }
+
   @Override
   public void stop() {
     // nothing to do
index d3d6797a4d3d7c707774164783bb8cadaecff55f..b2b26d951a7595620ee023273a41ef083daabcd7 100644 (file)
@@ -24,9 +24,12 @@ import com.google.common.collect.Sets;
 import java.util.Map;
 import java.util.function.Consumer;
 import javax.annotation.CheckForNull;
+import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
+import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
 import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
+import org.elasticsearch.common.settings.Settings;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -174,6 +177,49 @@ public class IndexCreatorTest {
       .contains("Create type metadatas/metadata");
   }
 
+  @Test
+  public void start_makes_metadata_index_read_write_if_read_only() {
+    run(new FakeIndexDefinition());
+
+    IndexMainType mainType = MetadataIndexDefinition.TYPE_METADATA;
+    makeReadOnly(mainType);
+
+    run(new FakeIndexDefinition());
+
+    assertThat(isNotReadOnly(mainType)).isTrue();
+  }
+
+  @Test
+  public void start_makes_index_read_write_if_read_only() {
+    FakeIndexDefinition fakeIndexDefinition = new FakeIndexDefinition();
+    IndexMainType fakeIndexMainType= FakeIndexDefinition.INDEX_TYPE.getMainType();
+    run(fakeIndexDefinition);
+
+    IndexMainType mainType = MetadataIndexDefinition.TYPE_METADATA;
+    makeReadOnly(mainType);
+    makeReadOnly(fakeIndexMainType);
+
+    run(fakeIndexDefinition);
+
+    assertThat(isNotReadOnly(mainType)).isTrue();
+    assertThat(isNotReadOnly(fakeIndexMainType)).isTrue();
+  }
+
+  private boolean isNotReadOnly(IndexMainType mainType) {
+    String indexName = mainType.getIndex().getName();
+    String readOnly = es.client().nativeClient().admin().indices().getSettings(new GetSettingsRequest().indices(indexName)).actionGet()
+      .getSetting(indexName, "index.blocks.read_only_allow_delete");
+    return readOnly == null;
+  }
+
+  private void makeReadOnly(IndexMainType mainType) {
+    Settings.Builder builder = Settings.builder();
+    builder.put("index.blocks.read_only_allow_delete", "true");
+    es.client().nativeClient().admin().indices()
+      .updateSettings(new UpdateSettingsRequest().indices(mainType.getIndex().getName()).settings(builder.build()))
+      .actionGet();
+  }
+
   private void enableBlueGreenDeployment() {
     settings.setProperty("sonar.blueGreenEnabled", "true");
   }
@@ -237,7 +283,7 @@ public class IndexCreatorTest {
   }
 
   private static class FakeIndexDefinition implements IndexDefinition {
-    private static final IndexMainType INDEX_TYPE = main(Index.simple("fakes"), "fake");
+    static final IndexMainType INDEX_TYPE = main(Index.simple("fakes"), "fake");
 
     @Override
     public void define(IndexDefinitionContext context) {