Shinsuke Sugaya 8 éve
szülő
commit
eb36d94d27

+ 38 - 2
src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java

@@ -15,6 +15,8 @@
  */
 package org.codelibs.fess.app.web.admin.upgrade;
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.function.Consumer;
 
 import javax.annotation.Resource;
@@ -127,6 +129,18 @@ public class AdminUpgradeAction extends FessAdminAction {
         return asHtml(path_AdminUpgrade_AdminUpgradeJsp).useForm(UpgradeForm.class);
     }
 
+    @Execute
+    public HtmlResponse reindexOnly(final ReindexForm form) {
+        validate(form, messages -> {}, () -> {
+            return asIndexHtml();
+        });
+        verifyToken(() -> asIndexHtml());
+        if (startReindex()) {
+            saveInfo(messages -> messages.addSuccessStartedDataUpdate(GLOBAL));
+        }
+        return redirect(getClass());
+    }
+
     @Execute
     public HtmlResponse upgradeFrom(final UpgradeForm form) {
         validate(form, messages -> {}, () -> {
@@ -139,7 +153,7 @@ public class AdminUpgradeAction extends FessAdminAction {
                 upgradeFrom11_0();
                 upgradeFromAll();
 
-                saveInfo(messages -> messages.addSuccessUpgradeFrom(GLOBAL));
+                saveInfo(messages -> messages.addSuccessStartedDataUpdate(GLOBAL));
 
                 systemHelper.reloadConfiguration();
             } catch (final Exception e) {
@@ -152,7 +166,7 @@ public class AdminUpgradeAction extends FessAdminAction {
                 upgradeFrom11_1();
                 upgradeFromAll();
 
-                saveInfo(messages -> messages.addSuccessUpgradeFrom(GLOBAL));
+                saveInfo(messages -> messages.addSuccessStartedDataUpdate(GLOBAL));
 
                 systemHelper.reloadConfiguration();
             } catch (final Exception e) {
@@ -185,6 +199,28 @@ public class AdminUpgradeAction extends FessAdminAction {
         if (existsIndex(indicesClient, crawlerIndex, IndicesOptions.fromOptions(false, true, true, true))) {
             deleteIndex(indicesClient, crawlerIndex, response -> {});
         }
+
+        startReindex();
+    }
+
+    private boolean startReindex() {
+        final String docIndex = "fess";
+        final String fromIndex = fessConfig.getIndexDocumentUpdateIndex();
+        final String toIndex = docIndex + "." + new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
+        if (fessEsClient.createIndex(docIndex, "doc", toIndex)) {
+            fessEsClient.admin().cluster().prepareHealth(toIndex).setWaitForYellowStatus().execute(ActionListener.wrap(response -> {
+                fessEsClient.addMapping(docIndex, "doc", toIndex);
+                fessEsClient.reindex(fromIndex, toIndex, false);
+                if (!fessEsClient.updateAlias(toIndex)) {
+                    logger.warn("Failed to update aliases for " + fromIndex + " and " + toIndex);
+                }
+            }, e -> {
+                logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex, e);
+            }));
+            return true;
+        }
+        saveError(messages -> messages.addErrorsFailedToReindex(GLOBAL, fromIndex, toIndex));
+        return false;
     }
 
     private void addFieldMapping(final IndicesAdminClient indicesClient, final String index, final String type, final String field,

+ 20 - 0
src/main/java/org/codelibs/fess/app/web/admin/upgrade/ReindexForm.java

@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2017 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.app.web.admin.upgrade;
+
+public class ReindexForm {
+
+}

+ 201 - 132
src/main/java/org/codelibs/fess/es/client/FessEsClient.java

@@ -74,6 +74,7 @@ import org.elasticsearch.action.DocWriteRequest;
 import org.elasticsearch.action.DocWriteRequest.OpType;
 import org.elasticsearch.action.DocWriteResponse.Result;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
+import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
@@ -302,7 +303,7 @@ public class FessEsClient implements Client {
             if (values.length == 2) {
                 final String configIndex = values[0];
                 final String configType = values[1];
-                boolean exists = false;
+
                 final String indexName;
                 final boolean isFessIndex = configIndex.equals("fess");
                 if (isFessIndex) {
@@ -310,156 +311,224 @@ public class FessEsClient implements Client {
                 } else {
                     indexName = configIndex;
                 }
-                try {
-                    final IndicesExistsResponse response =
-                            client.admin().indices().prepareExists(indexName).execute().actionGet(fessConfig.getIndexSearchTimeout());
-                    exists = response.isExists();
-                } catch (final Exception e) {
-                    // ignore
-            }
-            if (!exists) {
-                waitForConfigSyncStatus();
-                configListMap.getOrDefault(configIndex, Collections.emptyList()).forEach(
-                        path -> {
-                            String source = null;
-                            final String filePath = indexConfigPath + "/" + configIndex + "/" + path;
-                            try {
-                                source = FileUtil.readUTF8(filePath);
-                                try (CurlResponse response =
-                                        Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file")
-                                                .header("Content-Type", "application/json").param("path", path).body(source).execute()) {
-                                    if (response.getHttpStatusCode() == 200) {
-                                        logger.info("Register " + path + " to " + configIndex);
-                                    } else {
-                                        if (response.getContentException() != null) {
-                                            logger.warn("Invalid request for " + path + ".", response.getContentException());
-                                        } else {
-                                            logger.warn("Invalid request for " + path + ". The response is "
-                                                    + response.getContentAsString());
-                                        }
-                                    }
-                                }
-                            } catch (final Exception e) {
-                                logger.warn("Failed to register " + filePath, e);
-                            }
-                        });
-                try (CurlResponse response =
-                        Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/flush")
-                                .header("Content-Type", "application/json").execute()) {
-                    if (response.getHttpStatusCode() == 200) {
-                        logger.info("Flushed config files.");
+                boolean exists = existsIndex(indexName);
+                if (!exists) {
+                    final String createdIndexName;
+                    if (isFessIndex) {
+                        createdIndexName = generateNewIndexName(configIndex);
                     } else {
-                        logger.warn("Failed to flush config files.");
+                        createdIndexName = configIndex;
                     }
-                } catch (final Exception e) {
-                    logger.warn("Failed to flush config files.", e);
+                    createIndex(configIndex, configType, createdIndexName);
+                    createAlias(configIndex, createdIndexName);
                 }
 
-                final String createdIndexName;
+                final String updatedIndexName;
                 if (isFessIndex) {
-                    createdIndexName = generateNewIndexName(configIndex);
-                } else {
-                    createdIndexName = configIndex;
-                }
-                final String indexConfigFile = indexConfigPath + "/" + configIndex + ".json";
-                try {
-                    String source = FileUtil.readUTF8(indexConfigFile);
-                    final String dictionaryPath = System.getProperty("fess.dictionary.path", StringUtil.EMPTY);
-                    source = source.replaceAll(Pattern.quote("${fess.dictionary.path}"), dictionaryPath);
-                    final CreateIndexResponse indexResponse =
-                            client.admin().indices().prepareCreate(createdIndexName)
-                                    .setSource(source, XContentFactory.xContentType(source)).execute()
+                    client.admin().cluster().prepareHealth(fessConfig.getIndexDocumentUpdateIndex()).setWaitForYellowStatus().execute()
+                            .actionGet(fessConfig.getIndexIndicesTimeout());
+                    final GetIndexResponse response =
+                            client.admin().indices().prepareGetIndex().addIndices(fessConfig.getIndexDocumentUpdateIndex()).execute()
                                     .actionGet(fessConfig.getIndexIndicesTimeout());
-                    if (indexResponse.isAcknowledged()) {
-                        logger.info("Created " + createdIndexName + " index.");
-                    } else if (logger.isDebugEnabled()) {
-                        logger.debug("Failed to create " + createdIndexName + " index.");
+                    final String[] indices = response.indices();
+                    if (indices.length == 1) {
+                        updatedIndexName = indices[0];
+                    } else {
+                        updatedIndexName = configIndex;
                     }
-                } catch (final Exception e) {
-                    logger.warn(indexConfigFile + " is not found.", e);
+                } else {
+                    updatedIndexName = configIndex;
                 }
+                addMapping(configIndex, configType, updatedIndexName);
+            } else {
+                logger.warn("Invalid index config name: " + configName);
+            }
+        });
+    }
 
-                // alias
-                final String aliasConfigDirPath = indexConfigPath + "/" + configIndex + "/alias";
-                try {
-                    final File aliasConfigDir = ResourceUtil.getResourceAsFile(aliasConfigDirPath);
-                    if (aliasConfigDir.isDirectory()) {
-                        stream(aliasConfigDir.listFiles((dir, name) -> name.endsWith(".json"))).of(
-                                stream -> stream.forEach(f -> {
-                                    final String aliasName = f.getName().replaceFirst(".json$", "");
-                                    String source = FileUtil.readUTF8(f);
-                                    if (source.trim().equals("{}")) {
-                                        source = null;
-                                    }
-                                    final IndicesAliasesResponse response =
-                                            client.admin().indices().prepareAliases().addAlias(createdIndexName, aliasName, source)
-                                                    .execute().actionGet(fessConfig.getIndexIndicesTimeout());
-                                    if (response.isAcknowledged()) {
-                                        logger.info("Created " + aliasName + " alias for " + createdIndexName);
-                                    } else if (logger.isDebugEnabled()) {
-                                        logger.debug("Failed to create " + aliasName + " alias for " + createdIndexName);
-                                    }
-                                }));
-                    }
-                } catch (final ResourceNotFoundRuntimeException e) {
-                    // ignore
-                } catch (final Exception e) {
-                    logger.warn(aliasConfigDirPath + " is not found.", e);
-                }
+    public boolean existsIndex(final String indexName) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        boolean exists = false;
+        try {
+            final IndicesExistsResponse response =
+                    client.admin().indices().prepareExists(indexName).execute().actionGet(fessConfig.getIndexSearchTimeout());
+            exists = response.isExists();
+        } catch (final Exception e) {
+            // ignore
+        }
+        return exists;
+    }
+
+    public boolean reindex(final String fromIndex, final String toIndex, final boolean waitForCompletion) {
+        final String source = "{\"source\":{\"index\":\"" + fromIndex + "\"},\"dest\":{\"index\":\"" + toIndex + "\"}}";
+        try (CurlResponse response =
+                Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_reindex")
+                        .header("Content-Type", "application/json").param("wait_for_completion", Boolean.toString(waitForCompletion))
+                        .body(source).execute()) {
+            if (response.getHttpStatusCode() == 200) {
+                return true;
+            } else {
+                logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex);
+            }
+        } catch (IOException e) {
+            logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex, e);
+        }
+        return false;
+    }
+
+    public boolean createIndex(final String index, final String docType, final String indexName) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+
+        waitForConfigSyncStatus();
+        sendConfigFiles(index);
+
+        final String indexConfigFile = indexConfigPath + "/" + index + ".json";
+        try {
+            String source = FileUtil.readUTF8(indexConfigFile);
+            final String dictionaryPath = System.getProperty("fess.dictionary.path", StringUtil.EMPTY);
+            source = source.replaceAll(Pattern.quote("${fess.dictionary.path}"), dictionaryPath);
+            final CreateIndexResponse indexResponse =
+                    client.admin().indices().prepareCreate(indexName).setSource(source, XContentFactory.xContentType(source)).execute()
+                            .actionGet(fessConfig.getIndexIndicesTimeout());
+            if (indexResponse.isAcknowledged()) {
+                logger.info("Created " + indexName + " index.");
+                return true;
+            } else if (logger.isDebugEnabled()) {
+                logger.debug("Failed to create " + indexName + " index.");
             }
+        } catch (final Exception e) {
+            logger.warn(indexConfigFile + " is not found.", e);
+        }
 
-            final String updatedIndexName;
-            if (isFessIndex) {
-                client.admin().cluster().prepareHealth(fessConfig.getIndexDocumentUpdateIndex()).setWaitForYellowStatus().execute()
-                        .actionGet(fessConfig.getIndexIndicesTimeout());
-                final GetIndexResponse response =
-                        client.admin().indices().prepareGetIndex().addIndices(fessConfig.getIndexDocumentUpdateIndex()).execute()
+        return false;
+    }
+
+    public void addMapping(final String index, final String docType, final String indexName) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+
+        final GetMappingsResponse getMappingsResponse =
+                client.admin().indices().prepareGetMappings(indexName).execute().actionGet(fessConfig.getIndexIndicesTimeout());
+        final ImmutableOpenMap<String, MappingMetaData> indexMappings = getMappingsResponse.mappings().get(indexName);
+        if (indexMappings == null || !indexMappings.containsKey(docType)) {
+            String source = null;
+            final String mappingFile = indexConfigPath + "/" + index + "/" + docType + ".json";
+            try {
+                source = FileUtil.readUTF8(mappingFile);
+            } catch (final Exception e) {
+                logger.warn(mappingFile + " is not found.", e);
+            }
+            try {
+                final PutMappingResponse putMappingResponse =
+                        client.admin().indices().preparePutMapping(indexName).setType(docType)
+                                .setSource(source, XContentFactory.xContentType(source)).execute()
                                 .actionGet(fessConfig.getIndexIndicesTimeout());
-                final String[] indices = response.indices();
-                if (indices.length == 1) {
-                    updatedIndexName = indices[0];
+                if (putMappingResponse.isAcknowledged()) {
+                    logger.info("Created " + indexName + "/" + docType + " mapping.");
                 } else {
-                    updatedIndexName = configIndex;
+                    logger.warn("Failed to create " + indexName + "/" + docType + " mapping.");
                 }
-            } else {
-                updatedIndexName = configIndex;
-            }
-            final GetMappingsResponse getMappingsResponse =
-                    client.admin().indices().prepareGetMappings(updatedIndexName).execute().actionGet(fessConfig.getIndexIndicesTimeout());
-            final ImmutableOpenMap<String, MappingMetaData> indexMappings = getMappingsResponse.mappings().get(updatedIndexName);
-            if (indexMappings == null || !indexMappings.containsKey(configType)) {
-                String source = null;
-                final String mappingFile = indexConfigPath + "/" + configIndex + "/" + configType + ".json";
-                try {
-                    source = FileUtil.readUTF8(mappingFile);
-                } catch (final Exception e) {
-                    logger.warn(mappingFile + " is not found.", e);
+
+                final String dataPath = indexConfigPath + "/" + index + "/" + docType + ".bulk";
+                if (ResourceUtil.isExist(dataPath)) {
+                    insertBulkData(fessConfig, index, docType, dataPath);
                 }
-                try {
-                    final PutMappingResponse putMappingResponse =
-                            client.admin().indices().preparePutMapping(updatedIndexName).setType(configType)
-                                    .setSource(source, XContentFactory.xContentType(source)).execute()
-                                    .actionGet(fessConfig.getIndexIndicesTimeout());
-                    if (putMappingResponse.isAcknowledged()) {
-                        logger.info("Created " + updatedIndexName + "/" + configType + " mapping.");
-                    } else {
-                        logger.warn("Failed to create " + updatedIndexName + "/" + configType + " mapping.");
-                    }
+            } catch (final Exception e) {
+                logger.warn("Failed to create " + indexName + "/" + docType + " mapping.", e);
+            }
+        } else if (logger.isDebugEnabled()) {
+            logger.debug(indexName + "/" + docType + " mapping exists.");
+        }
+    }
+
+    public boolean updateAlias(final String newIndex) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        String updateAlias = fessConfig.getIndexDocumentUpdateIndex();
+        String searchAlias = fessConfig.getIndexDocumentSearchIndex();
+        final GetIndexResponse response1 =
+                client.admin().indices().prepareGetIndex().addIndices(updateAlias).execute().actionGet(fessConfig.getIndexIndicesTimeout());
+        final String[] updateIndices = response1.indices();
+        final GetIndexResponse response2 =
+                client.admin().indices().prepareGetIndex().addIndices(searchAlias).execute().actionGet(fessConfig.getIndexIndicesTimeout());
+        final String[] searchIndices = response2.indices();
+
+        IndicesAliasesRequestBuilder builder =
+                client.admin().indices().prepareAliases().addAlias(newIndex, updateAlias).addAlias(newIndex, searchAlias);
+        for (String index : updateIndices) {
+            builder.removeAlias(index, updateAlias);
+        }
+        for (String index : searchIndices) {
+            builder.removeAlias(index, searchAlias);
+        }
+        IndicesAliasesResponse response = builder.execute().actionGet(fessConfig.getIndexIndicesTimeout());
+        return response.isAcknowledged();
+    }
+
+    protected void createAlias(final String index, final String createdIndexName) {
+        final FessConfig fessConfig = ComponentUtil.getFessConfig();
+        // alias
+        final String aliasConfigDirPath = indexConfigPath + "/" + index + "/alias";
+        try {
+            final File aliasConfigDir = ResourceUtil.getResourceAsFile(aliasConfigDirPath);
+            if (aliasConfigDir.isDirectory()) {
+                stream(aliasConfigDir.listFiles((dir, name) -> name.endsWith(".json"))).of(
+                        stream -> stream.forEach(f -> {
+                            final String aliasName = f.getName().replaceFirst(".json$", "");
+                            String source = FileUtil.readUTF8(f);
+                            if (source.trim().equals("{}")) {
+                                source = null;
+                            }
+                            final IndicesAliasesResponse response =
+                                    client.admin().indices().prepareAliases().addAlias(createdIndexName, aliasName, source).execute()
+                                            .actionGet(fessConfig.getIndexIndicesTimeout());
+                            if (response.isAcknowledged()) {
+                                logger.info("Created " + aliasName + " alias for " + createdIndexName);
+                            } else if (logger.isDebugEnabled()) {
+                                logger.debug("Failed to create " + aliasName + " alias for " + createdIndexName);
+                            }
+                        }));
+            }
+        } catch (final ResourceNotFoundRuntimeException e) {
+            // ignore
+        } catch (final Exception e) {
+            logger.warn(aliasConfigDirPath + " is not found.", e);
+        }
+    }
 
-                    final String dataPath = indexConfigPath + "/" + configIndex + "/" + configType + ".bulk";
-                    if (ResourceUtil.isExist(dataPath)) {
-                        insertBulkData(fessConfig, configIndex, configType, dataPath);
+    protected void sendConfigFiles(final String index) {
+        configListMap.getOrDefault(index, Collections.emptyList()).forEach(
+                path -> {
+                    String source = null;
+                    final String filePath = indexConfigPath + "/" + index + "/" + path;
+                    try {
+                        source = FileUtil.readUTF8(filePath);
+                        try (CurlResponse response =
+                                Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file")
+                                        .header("Content-Type", "application/json").param("path", path).body(source).execute()) {
+                            if (response.getHttpStatusCode() == 200) {
+                                logger.info("Register " + path + " to " + index);
+                            } else {
+                                if (response.getContentException() != null) {
+                                    logger.warn("Invalid request for " + path + ".", response.getContentException());
+                                } else {
+                                    logger.warn("Invalid request for " + path + ". The response is " + response.getContentAsString());
+                                }
+                            }
+                        }
+                    } catch (final Exception e) {
+                        logger.warn("Failed to register " + filePath, e);
                     }
-                } catch (final Exception e) {
-                    logger.warn("Failed to create " + updatedIndexName + "/" + configType + " mapping.", e);
-                }
-            } else if (logger.isDebugEnabled()) {
-                logger.debug(updatedIndexName + "/" + configType + " mapping exists.");
+                });
+        try (CurlResponse response =
+                Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/flush")
+                        .header("Content-Type", "application/json").execute()) {
+            if (response.getHttpStatusCode() == 200) {
+                logger.info("Flushed config files.");
+            } else {
+                logger.warn("Failed to flush config files.");
             }
-        } else {
-            logger.warn("Invalid index config name: " + configName);
+        } catch (final Exception e) {
+            logger.warn("Failed to flush config files.", e);
         }
-    })  ;
     }
 
     protected String generateNewIndexName(final String configIndex) {

+ 6 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -2634,9 +2634,15 @@ public class FessLabels extends UserMessages {
     /** The key of the message: Data Migration */
     public static final String LABELS_upgrade_data_migration = "{labels.upgrade_data_migration}";
 
+    /** The key of the message: Reindex */
+    public static final String LABELS_upgrade_reindex = "{labels.upgrade_reindex}";
+
     /** The key of the message: Start */
     public static final String LABELS_upgrade_start_button = "{labels.upgrade_start_button}";
 
+    /** The key of the message: Start */
+    public static final String LABELS_reindex_start_button = "{labels.reindex_start_button}";
+
     /** The key of the message: Version */
     public static final String LABELS_TARGET_VERSION = "{labels.targetVersion}";
 

+ 42 - 6
src/main/java/org/codelibs/fess/mylasta/action/FessMessages.java

@@ -314,6 +314,9 @@ public class FessMessages extends FessLabels {
     /** The key of the message: Failed to upgrade from {0}: {1} */
     public static final String ERRORS_failed_to_upgrade_from = "{errors.failed_to_upgrade_from}";
 
+    /** The key of the message: Failed to start reindexing from {0} to {1} */
+    public static final String ERRORS_failed_to_reindex = "{errors.failed_to_reindex}";
+
     /** The key of the message: Failed to read request file: {0} */
     public static final String ERRORS_failed_to_read_request_file = "{errors.failed_to_read_request_file}";
 
@@ -416,8 +419,11 @@ public class FessMessages extends FessLabels {
     /** The key of the message: Changed your password. */
     public static final String SUCCESS_changed_password = "{success.changed_password}";
 
-    /** The key of the message: Upgraded data. */
-    public static final String SUCCESS_upgrade_from = "{success.upgrade_from}";
+    /** The key of the message: Started data update process. */
+    public static final String SUCCESS_started_data_update = "{success.started_data_update}";
+
+    /** The key of the message: Started reindexing. */
+    public static final String SUCCESS_reindex_started = "{success.reindex_started}";
 
     /** The key of the message: Bulk process is started. */
     public static final String SUCCESS_bulk_process_started = "{success.bulk_process_started}";
@@ -1845,6 +1851,22 @@ public class FessMessages extends FessLabels {
         return this;
     }
 
+    /**
+     * Add the created action message for the key 'errors.failed_to_reindex' with parameters.
+     * <pre>
+     * message: Failed to start reindexing from {0} to {1}
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @param arg0 The parameter arg0 for message. (NotNull)
+     * @param arg1 The parameter arg1 for message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsFailedToReindex(String property, String arg0, String arg1) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(ERRORS_failed_to_reindex, arg0, arg1));
+        return this;
+    }
+
     /**
      * Add the created action message for the key 'errors.failed_to_read_request_file' with parameters.
      * <pre>
@@ -2339,16 +2361,30 @@ public class FessMessages extends FessLabels {
     }
 
     /**
-     * Add the created action message for the key 'success.upgrade_from' with parameters.
+     * Add the created action message for the key 'success.started_data_update' with parameters.
+     * <pre>
+     * message: Started data update process.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addSuccessStartedDataUpdate(String property) {
+        assertPropertyNotNull(property);
+        add(property, new UserMessage(SUCCESS_started_data_update));
+        return this;
+    }
+
+    /**
+     * Add the created action message for the key 'success.reindex_started' with parameters.
      * <pre>
-     * message: Upgraded data.
+     * message: Started reindexing.
      * </pre>
      * @param property The property name for the message. (NotNull)
      * @return this. (NotNull)
      */
-    public FessMessages addSuccessUpgradeFrom(String property) {
+    public FessMessages addSuccessReindexStarted(String property) {
         assertPropertyNotNull(property);
-        add(property, new UserMessage(SUCCESS_upgrade_from));
+        add(property, new UserMessage(SUCCESS_reindex_started));
         return this;
     }
 

+ 2 - 0
src/main/resources/fess_label.properties

@@ -868,7 +868,9 @@ labels.user_homeDirectory=Home Directory
 labels.homeDirectory=Home Directory
 labels.upgrade_title_configuration=Upgrade
 labels.upgrade_data_migration=Data Migration
+labels.upgrade_reindex=Reindex
 labels.upgrade_start_button=Start
+labels.reindex_start_button=Start
 labels.targetVersion=Version
 labels.target_version=Version From
 labels.esreq_configuration=Request to elasticsearch

+ 2 - 0
src/main/resources/fess_label_en.properties

@@ -868,7 +868,9 @@ labels.user_homeDirectory=Home Directory
 labels.homeDirectory=Home Directory
 labels.upgrade_title_configuration=Upgrade
 labels.upgrade_data_migration=Data Migration
+labels.upgrade_reindex=Reindex
 labels.upgrade_start_button=Start
+labels.reindex_start_button=Start
 labels.targetVersion=Version
 labels.target_version=Version From
 labels.esreq_configuration=Request to elasticsearch

+ 2 - 0
src/main/resources/fess_label_ja.properties

@@ -870,7 +870,9 @@ labels.user_homeDirectory=\u30db\u30fc\u30e0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
 labels.homeDirectory=\u30db\u30fc\u30e0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
 labels.upgrade_title_configuration=\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9
 labels.upgrade_data_migration=\u30c7\u30fc\u30bf\u79fb\u884c
+labels.upgrade_reindex=\u518d\u30a4\u30f3\u30c7\u30af\u30b7\u30f3\u30b0
 labels.upgrade_start_button=\u958b\u59cb
+labels.reindex_start_button=\u958b\u59cb
 labels.targetVersion=\u5bfe\u8c61\u30d0\u30fc\u30b8\u30e7\u30f3
 labels.target_version=\u5bfe\u8c61\u30d0\u30fc\u30b8\u30e7\u30f3
 labels.esreq_configuration=elasticsearch\u3078\u306e\u30ea\u30af\u30a8\u30b9\u30c8

+ 3 - 1
src/main/resources/fess_message.properties

@@ -126,6 +126,7 @@ errors.no_user_for_changing_password=The current password is incorrect.
 errors.failed_to_change_password=Failed to change your password.
 errors.unknown_version_for_upgrade=Unknown version information.
 errors.failed_to_upgrade_from=Failed to upgrade from {0}: {1}
+errors.failed_to_reindex=Failed to start reindexing from {0} to {1}
 errors.failed_to_read_request_file=Failed to read request file: {0}
 errors.invalid_header_for_request_file=Invalid header: {0}
 errors.could_not_delete_logged_in_user=Could not delete logged in user.
@@ -163,7 +164,8 @@ success.upload_mapping_file=Uploaded Mapping file.
 success.send_testmail=Sent the test mail.
 success.job_log_delete_all=Deleted job logs.
 success.changed_password=Changed your password.
-success.upgrade_from=Upgraded data.
+success.started_data_update=Started data update process.
+success.reindex_started=Started reindexing.
 success.bulk_process_started=Bulk process is started.
 
 success.crud_create_crud_table=Created data.

+ 3 - 1
src/main/resources/fess_message_en.properties

@@ -122,6 +122,7 @@ errors.no_user_for_changing_password=The current password is incorrect.
 errors.failed_to_change_password=Failed to change your password.
 errors.unknown_version_for_upgrade=Unknown version information.
 errors.failed_to_upgrade_from=Failed to upgrade from {0}.
+errors.failed_to_reindex=Failed to start reindexing from {0} to {1}
 errors.failed_to_read_request_file=Failed to read request file: {0}
 errors.invalid_header_for_request_file=Invalid header: {0}
 errors.could_not_delete_logged_in_user=Could not delete logged in user.
@@ -159,7 +160,8 @@ success.upload_mapping_file=Uploaded Mapping file.
 success.send_testmail=Sent the test mail.
 success.job_log_delete_all=Deleted job logs.
 success.changed_password=Changed your password.
-success.upgrade_from=Upgraded data.
+success.started_data_update=Started data update process.
+success.reindex_started=Started reindexing.
 success.bulk_process_started=Bulk process is started.
 
 success.crud_create_crud_table=Created data.

+ 3 - 1
src/main/resources/fess_message_ja.properties

@@ -129,6 +129,7 @@ errors.no_user_for_changing_password=\u73fe\u5728\u306e\u30d1\u30b9\u30ef\u30fc\
 errors.failed_to_change_password=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u5909\u66f4\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
 errors.unknown_version_for_upgrade=\u4e0d\u660e\u306a\u30d0\u30fc\u30b8\u30e7\u30f3\u60c5\u5831\u3067\u3059\u3002
 errors.failed_to_upgrade_from={0}\u304b\u3089\u306e\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
+errors.failed_to_reindex={0}\u304b\u3089{1}\u3078\u306e\u518d\u30a4\u30f3\u30c7\u30af\u30b7\u30f3\u30b0\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
 errors.failed_to_read_request_file=\u30ea\u30af\u30a8\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f: {0}
 errors.invalid_header_for_request_file=\u30d8\u30c3\u30c0\u30fc\u884c\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093: {0}
 errors.could_not_delete_logged_in_user=\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3044\u308b\u30e6\u30fc\u30b6\u30fc\u306f\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002
@@ -152,7 +153,8 @@ success.upload_mapping_file = \u30de\u30c3\u30d4\u30f3\u30b0\u30d5\u30a1\u30a4\u
 success.send_testmail=\u30c6\u30b9\u30c8\u30e1\u30fc\u30eb\u3092\u9001\u4fe1\u3057\u307e\u3057\u305f\u3002
 success.job_log_delete_all=\u30b8\u30e7\u30d6\u30ed\u30b0\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.changed_password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5909\u66f4\u3057\u307e\u3057\u305f\u3002
-success.upgrade_from=\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002
+success.started_data_update=\u30c7\u30fc\u30bf\u66f4\u65b0\u51e6\u7406\u3092\u958b\u59cb\u3057\u307e\u3057\u305f\u3002
+success.reindex_started=\u518d\u30a4\u30f3\u30c7\u30af\u30b7\u30f3\u30b0\u3092\u958b\u59cb\u3057\u307e\u3057\u305f\u3002
 success.bulk_process_started=\u30d0\u30eb\u30af\u51e6\u7406\u3092\u958b\u59cb\u3057\u307e\u3057\u305f\u3002
 
 success.crud_create_crud_table = \u30c7\u30fc\u30bf\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\u3002

+ 0 - 1
src/main/resources/fess_message_ko.properties

@@ -152,7 +152,6 @@ success.upload_mapping_file = \ub9e4\ud551 \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc
 success.send_testmail = \ud14c\uc2a4\ud2b8 \uc774\uba54\uc77c\uc744 \ubcf4\ub0c8\uc2b5\ub2c8\ub2e4.
 success.job_log_delete_all = \uc791\uc5c5 \ub85c\uadf8\ub97c \uc0ad\uc81c\ud588\uc2b5\ub2c8\ub2e4.
 success.changed_password = \uc554\ud638\ub97c \ubcc0\uacbd\ud588\uc2b5\ub2c8\ub2e4.
-success.upgrade_from = \ub370\uc774\ud130\ub97c \uc5c5\ub370\uc774\ud2b8\ud588\uc2b5\ub2c8\ub2e4.
 success.bulk_process_started = \uc77c\uad04 \ucc98\ub9ac\ub97c \uc2dc\uc791\ud588\uc2b5\ub2c8\ub2e4.
 
 success.crud_create_crud_table = \ub370\uc774\ud130\ub97c \uc791\uc131\ud588\uc2b5\ub2c8\ub2e4.

+ 0 - 1
src/main/resources/fess_message_ru.properties

@@ -157,7 +157,6 @@ success.upload_mapping_file=Uploaded Mapping file.
 success.send_testmail=Sent the test mail.
 success.job_log_delete_all=Deleted job logs.
 success.changed_password=Changed your password.
-success.upgrade_from=Upgraded data.
 success.bulk_process_started=Bulk process is started.
 
 success.crud_create_crud_table=Created data.

+ 37 - 4
src/main/webapp/WEB-INF/view/admin/upgrade/admin_upgrade.jsp

@@ -20,8 +20,8 @@
 				</h1>
 			</section>
 			<section class="content">
-				<la:form action="/admin/upgrade/">
-					<div class="row">
+				<div class="row">
+					<la:form action="/admin/upgrade/">
 						<div class="col-md-12">
 							<div class="box box-primary">
 								<div class="box-header with-border">
@@ -63,8 +63,41 @@
 							</div>
 							<!-- /.box -->
 						</div>
-					</div>
-				</la:form>
+					</la:form>
+					<la:form action="/admin/upgrade/">
+						<div class="col-md-12">
+							<div class="box box-primary">
+								<div class="box-header with-border">
+									<h3 class="box-title">
+										<la:message key="labels.upgrade_reindex" />
+									</h3>
+								</div>
+								<!-- /.box-header -->
+								<div class="box-body">
+									<%-- Message: BEGIN --%>
+									<div>
+										<la:info id="msg" message="true">
+											<div class="alert alert-info">${msg}</div>
+										</la:info>
+										<la:errors />
+									</div>
+									<%-- Message: END --%>
+								</div>
+								<!-- /.box-body -->
+								<div class="box-footer">
+									<button type="submit" class="btn btn-primary"
+										name="reindexOnly"
+										value="<la:message key="labels.reindex_start_button"/>">
+										<i class="fa fa-arrow-circle-right"></i>
+										<la:message key="labels.reindex_start_button" />
+									</button>
+								</div>
+								<!-- /.box-footer -->
+							</div>
+							<!-- /.box -->
+						</div>
+					</la:form>
+				</div>
 			</section>
 		</div>
 		<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>