Search in sources :

Example 21 with AliasMetadata

use of org.graylog.shaded.elasticsearch7.org.elasticsearch.cluster.metadata.AliasMetadata in project crate by crate.

the class TableAliasIntegrationTest method testPartitionedTableKeepsAliasAfterSchemaUpdate.

@Test
public void testPartitionedTableKeepsAliasAfterSchemaUpdate() throws Exception {
    execute("create table t (name string, p string) partitioned by (p) " + "clustered into 2 shards with (number_of_replicas = 0)");
    ensureYellow();
    execute("insert into t (name, p) values ('Arthur', 'a')");
    execute("insert into t (name, p) values ('Trillian', 'a')");
    execute("alter table t add column age integer");
    execute("insert into t (name, p) values ('Marvin', 'b')");
    waitNoPendingTasksOnAll();
    refresh();
    execute("select count(*) from t");
    assertThat(response.rowCount(), is(1L));
    assertThat((Long) response.rows()[0][0], is(3L));
    GetIndexTemplatesResponse indexTemplatesResponse = client().admin().indices().prepareGetTemplates(".partitioned.t.").execute().actionGet();
    IndexTemplateMetaData indexTemplateMetaData = indexTemplatesResponse.getIndexTemplates().get(0);
    AliasMetaData t = indexTemplateMetaData.aliases().get("t");
    assertThat(t.alias(), is("t"));
    execute("select partitioned_by from information_schema.tables where table_name = 't'");
    assertThat((String) ((Object[]) response.rows()[0][0])[0], is("p"));
}
Also used : AliasMetaData(org.elasticsearch.cluster.metadata.AliasMetaData) GetIndexTemplatesResponse(org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse) IndexTemplateMetaData(org.elasticsearch.cluster.metadata.IndexTemplateMetaData) Test(org.junit.Test)

Example 22 with AliasMetadata

use of org.graylog.shaded.elasticsearch7.org.elasticsearch.cluster.metadata.AliasMetadata in project crate by crate.

the class AlterTableOperation method updateTemplate.

private CompletableFuture<Long> updateTemplate(Map<String, Object> newMappings, Settings newSettings, TableIdent tableIdent) {
    String templateName = PartitionName.templateName(tableIdent.schema(), tableIdent.name());
    IndexTemplateMetaData indexTemplateMetaData = clusterService.state().metaData().templates().get(templateName);
    if (indexTemplateMetaData == null) {
        return CompletableFutures.failedFuture(new RuntimeException("Template for partitioned table is missing"));
    }
    // merge mappings
    Map<String, Object> mapping = mergeTemplateMapping(indexTemplateMetaData, newMappings);
    // merge settings
    Settings.Builder settingsBuilder = Settings.builder();
    settingsBuilder.put(indexTemplateMetaData.settings());
    settingsBuilder.put(newSettings);
    PutIndexTemplateRequest request = new PutIndexTemplateRequest(templateName).create(false).mapping(Constants.DEFAULT_MAPPING_TYPE, mapping).order(indexTemplateMetaData.order()).settings(settingsBuilder.build()).template(indexTemplateMetaData.template());
    for (ObjectObjectCursor<String, AliasMetaData> container : indexTemplateMetaData.aliases()) {
        Alias alias = new Alias(container.key);
        request.alias(alias);
    }
    FutureActionListener<PutIndexTemplateResponse, Long> listener = new FutureActionListener<>(LONG_NULL_FUNCTION);
    transportActionProvider.transportPutIndexTemplateAction().execute(request, listener);
    return listener;
}
Also used : PutIndexTemplateRequest(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest) FutureActionListener(io.crate.action.FutureActionListener) AliasMetaData(org.elasticsearch.cluster.metadata.AliasMetaData) IndexTemplateMetaData(org.elasticsearch.cluster.metadata.IndexTemplateMetaData) Alias(org.elasticsearch.action.admin.indices.alias.Alias) PutIndexTemplateResponse(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse) Settings(org.elasticsearch.common.settings.Settings)

Example 23 with AliasMetadata

use of org.graylog.shaded.elasticsearch7.org.elasticsearch.cluster.metadata.AliasMetadata in project crate by crate.

the class IndexTemplateUpgrader method archiveUnknownOrInvalidSettings.

/**
 * Filter out all unknown/old/invalid settings. Archiving them *only* is not working as they would be "un-archived"
 * by {@link IndexTemplateMetadata.Builder#fromXContent} logic to prefix all settings with `index.` when applying
 * the new cluster state.
 */
private HashMap<String, IndexTemplateMetadata> archiveUnknownOrInvalidSettings(Map<String, IndexTemplateMetadata> templates) {
    HashMap<String, IndexTemplateMetadata> upgradedTemplates = new HashMap<>(templates.size());
    for (Map.Entry<String, IndexTemplateMetadata> entry : templates.entrySet()) {
        IndexTemplateMetadata templateMetadata = entry.getValue();
        Settings.Builder settingsBuilder = Settings.builder().put(templateMetadata.settings());
        String templateName = entry.getKey();
        // only process partition table templates
        if (IndexParts.isPartitioned(templateName) == false) {
            upgradedTemplates.put(templateName, templateMetadata);
            continue;
        }
        Settings settings = DEFAULT_SCOPED_SETTINGS.archiveUnknownOrInvalidSettings(settingsBuilder.build(), e -> {
        }, (e, ex) -> {
        }).filter(k -> k.startsWith(ARCHIVED_SETTINGS_PREFIX) == false);
        IndexTemplateMetadata.Builder builder = IndexTemplateMetadata.builder(templateName).patterns(templateMetadata.patterns()).order(templateMetadata.order()).settings(settings);
        try {
            for (ObjectObjectCursor<String, CompressedXContent> cursor : templateMetadata.getMappings()) {
                var mappingSource = XContentHelper.toMap(cursor.value.compressedReference(), XContentType.JSON);
                Object defaultMapping = mappingSource.get("default");
                if (defaultMapping instanceof Map && ((Map<?, ?>) defaultMapping).containsKey("_all")) {
                    Map<?, ?> mapping = (Map<?, ?>) defaultMapping;
                    // Support for `_all` was removed (in favour of `copy_to`.
                    // We never utilized this but always set `_all: {enabled: false}` if you created a table using SQL in earlier version, so we can safely drop it.
                    mapping.remove("_all");
                    builder.putMapping(cursor.key, new CompressedXContent(BytesReference.bytes(XContentFactory.jsonBuilder().value(mappingSource))));
                } else {
                    builder.putMapping(cursor.key, cursor.value);
                }
            }
        } catch (IOException e) {
            logger.error("Error while trying to upgrade template '" + templateName + "'", e);
            continue;
        }
        for (ObjectObjectCursor<String, AliasMetadata> container : templateMetadata.aliases()) {
            builder.putAlias(container.value);
        }
        upgradedTemplates.put(templateName, builder.build());
    }
    return upgradedTemplates;
}
Also used : IndexParts(io.crate.metadata.IndexParts) XContentFactory(org.elasticsearch.common.xcontent.XContentFactory) XContentType(org.elasticsearch.common.xcontent.XContentType) IOException(java.io.IOException) HashMap(java.util.HashMap) UnaryOperator(java.util.function.UnaryOperator) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) BytesReference(org.elasticsearch.common.bytes.BytesReference) XContentHelper(org.elasticsearch.common.xcontent.XContentHelper) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) Logger(org.apache.logging.log4j.Logger) Settings(org.elasticsearch.common.settings.Settings) CompressedXContent(org.elasticsearch.common.compress.CompressedXContent) Map(java.util.Map) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) DEFAULT_SCOPED_SETTINGS(org.elasticsearch.common.settings.IndexScopedSettings.DEFAULT_SCOPED_SETTINGS) LogManager(org.apache.logging.log4j.LogManager) ARCHIVED_SETTINGS_PREFIX(org.elasticsearch.common.settings.AbstractScopedSettings.ARCHIVED_SETTINGS_PREFIX) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) HashMap(java.util.HashMap) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) IOException(java.io.IOException) CompressedXContent(org.elasticsearch.common.compress.CompressedXContent) HashMap(java.util.HashMap) Map(java.util.Map) Settings(org.elasticsearch.common.settings.Settings)

Example 24 with AliasMetadata

use of org.graylog.shaded.elasticsearch7.org.elasticsearch.cluster.metadata.AliasMetadata in project crate by crate.

the class TransportCreatePartitionsAction method executeCreateIndices.

/**
 * This code is more or less the same as the stuff in {@link MetadataCreateIndexService}
 * but optimized for bulk operation without separate mapping/alias/index settings.
 */
private ClusterState executeCreateIndices(ClusterState currentState, CreatePartitionsRequest request) throws Exception {
    List<String> indicesToCreate = new ArrayList<>(request.indices().size());
    List<String> removalReasons = new ArrayList<>(request.indices().size());
    List<Index> createdIndices = new ArrayList<>(request.indices().size());
    try {
        validateAndFilterExistingIndices(currentState, indicesToCreate, request);
        if (indicesToCreate.isEmpty()) {
            return currentState;
        }
        Map<String, Map<String, Object>> mappings = new HashMap<>();
        Map<String, AliasMetadata> templatesAliases = new HashMap<>();
        List<String> templateNames = new ArrayList<>();
        List<IndexTemplateMetadata> templates = findTemplates(request, currentState);
        applyTemplates(mappings, templatesAliases, templateNames, templates);
        Metadata.Builder newMetadataBuilder = Metadata.builder(currentState.metadata());
        for (String index : indicesToCreate) {
            Settings indexSettings = createIndexSettings(currentState, templates);
            shardLimitValidator.validateShardLimit(indexSettings, currentState);
            int routingNumShards = IndexMetadata.INDEX_NUMBER_OF_ROUTING_SHARDS_SETTING.get(indexSettings);
            String testIndex = indicesToCreate.get(0);
            IndexMetadata.Builder tmpImdBuilder = IndexMetadata.builder(testIndex).setRoutingNumShards(routingNumShards);
            // Set up everything, now locally create the index to see that things are ok, and apply
            final IndexMetadata tmpImd = tmpImdBuilder.settings(indexSettings).build();
            ActiveShardCount waitForActiveShards = tmpImd.getWaitForActiveShards();
            if (!waitForActiveShards.validate(tmpImd.getNumberOfReplicas())) {
                throw new IllegalArgumentException("invalid wait_for_active_shards[" + waitForActiveShards + "]: cannot be greater than number of shard copies [" + (tmpImd.getNumberOfReplicas() + 1) + "]");
            }
            // create the index here (on the master) to validate it can be created, as well as adding the mapping
            IndexService indexService = indicesService.createIndex(tmpImd, Collections.emptyList(), false);
            createdIndices.add(indexService.index());
            // now add the mappings
            MapperService mapperService = indexService.mapperService();
            if (!mappings.isEmpty()) {
                assert mappings.size() == 1 : "Must have at most 1 mapping type";
                var entry = mappings.entrySet().iterator().next();
                try {
                    mapperService.merge(entry.getKey(), entry.getValue(), MapperService.MergeReason.MAPPING_UPDATE);
                } catch (MapperParsingException mpe) {
                    removalReasons.add("failed on parsing mappings on index creation");
                    throw mpe;
                }
            }
            // now, update the mappings with the actual source
            HashMap<String, MappingMetadata> mappingsMetadata = new HashMap<>();
            DocumentMapper mapper = mapperService.documentMapper();
            if (mapper != null) {
                MappingMetadata mappingMd = new MappingMetadata(mapper);
                mappingsMetadata.put(mapper.type(), mappingMd);
            }
            final IndexMetadata.Builder indexMetadataBuilder = IndexMetadata.builder(index).setRoutingNumShards(routingNumShards).settings(indexSettings);
            for (MappingMetadata mappingMd : mappingsMetadata.values()) {
                indexMetadataBuilder.putMapping(mappingMd);
            }
            for (AliasMetadata aliasMetadata : templatesAliases.values()) {
                indexMetadataBuilder.putAlias(aliasMetadata);
            }
            indexMetadataBuilder.state(IndexMetadata.State.OPEN);
            final IndexMetadata indexMetadata;
            try {
                indexMetadata = indexMetadataBuilder.build();
            } catch (Exception e) {
                removalReasons.add("failed to build index metadata");
                throw e;
            }
            logger.info("[{}] creating index, cause [bulk], templates {}, shards [{}]/[{}], mappings {}", index, templateNames, indexMetadata.getNumberOfShards(), indexMetadata.getNumberOfReplicas(), mappings.keySet());
            indexService.getIndexEventListener().beforeIndexAddedToCluster(indexMetadata.getIndex(), indexMetadata.getSettings());
            newMetadataBuilder.put(indexMetadata, false);
            removalReasons.add("cleaning up after validating index on master");
        }
        Metadata newMetadata = newMetadataBuilder.build();
        ClusterState updatedState = ClusterState.builder(currentState).metadata(newMetadata).build();
        RoutingTable.Builder routingTableBuilder = RoutingTable.builder(updatedState.routingTable());
        for (String index : indicesToCreate) {
            routingTableBuilder.addAsNew(updatedState.metadata().index(index));
        }
        return allocationService.reroute(ClusterState.builder(updatedState).routingTable(routingTableBuilder.build()).build(), "bulk-index-creation");
    } finally {
        for (int i = 0; i < createdIndices.size(); i++) {
            // Index was already partially created - need to clean up
            String removalReason = removalReasons.size() > i ? removalReasons.get(i) : "failed to create index";
            indicesService.removeIndex(createdIndices.get(i), IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED, removalReason);
        }
    }
}
Also used : MapperParsingException(org.elasticsearch.index.mapper.MapperParsingException) HashMap(java.util.HashMap) IndexService(org.elasticsearch.index.IndexService) MetadataCreateIndexService(org.elasticsearch.cluster.metadata.MetadataCreateIndexService) ArrayList(java.util.ArrayList) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) MappingMetadata(org.elasticsearch.cluster.metadata.MappingMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) Index(org.elasticsearch.index.Index) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) Settings(org.elasticsearch.common.settings.Settings) ClusterState(org.elasticsearch.cluster.ClusterState) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) ActiveShardCount(org.elasticsearch.action.support.ActiveShardCount) ElasticsearchException(org.elasticsearch.ElasticsearchException) ResourceAlreadyExistsException(org.elasticsearch.ResourceAlreadyExistsException) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException) MapperParsingException(org.elasticsearch.index.mapper.MapperParsingException) IOException(java.io.IOException) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) Map(java.util.Map) HashMap(java.util.HashMap) MappingMetadata(org.elasticsearch.cluster.metadata.MappingMetadata) MapperService(org.elasticsearch.index.mapper.MapperService)

Example 25 with AliasMetadata

use of org.graylog.shaded.elasticsearch7.org.elasticsearch.cluster.metadata.AliasMetadata in project crate by crate.

the class RestoreService method restoreSnapshot.

/**
 * Restores snapshot specified in the restore request.
 *
 * @param request  restore request
 * @param listener restore listener
 */
public void restoreSnapshot(final RestoreRequest request, final ActionListener<RestoreCompletionResponse> listener) {
    try {
        // Read snapshot info and metadata from the repository
        final String repositoryName = request.repositoryName;
        Repository repository = repositoriesService.repository(repositoryName);
        final StepListener<RepositoryData> repositoryDataListener = new StepListener<>();
        repository.getRepositoryData(repositoryDataListener);
        repositoryDataListener.whenComplete(repositoryData -> {
            final String snapshotName = request.snapshotName;
            final Optional<SnapshotId> matchingSnapshotId = repositoryData.getSnapshotIds().stream().filter(s -> snapshotName.equals(s.getName())).findFirst();
            if (matchingSnapshotId.isPresent() == false) {
                throw new SnapshotRestoreException(repositoryName, snapshotName, "snapshot does not exist");
            }
            final SnapshotId snapshotId = matchingSnapshotId.get();
            repository.getSnapshotInfo(snapshotId, ActionListener.delegateFailure(listener, (delegate, snapshotInfo) -> {
                final Snapshot snapshot = new Snapshot(repositoryName, snapshotId);
                // Make sure that we can restore from this snapshot
                validateSnapshotRestorable(repositoryName, snapshotInfo);
                // Resolve the indices from the snapshot that need to be restored
                final List<String> indicesInSnapshot = request.includeIndices() ? filterIndices(snapshotInfo.indices(), request.indices(), request.indicesOptions()) : List.of();
                final StepListener<Metadata> globalMetadataListener = new StepListener<>();
                if (request.includeCustomMetadata() || request.includeGlobalSettings() || request.allTemplates() || (request.templates() != null && request.templates().length > 0)) {
                    repository.getSnapshotGlobalMetadata(snapshotId, globalMetadataListener);
                } else {
                    globalMetadataListener.onResponse(Metadata.EMPTY_METADATA);
                }
                globalMetadataListener.whenComplete(globalMetadata -> {
                    var metadataBuilder = Metadata.builder(globalMetadata);
                    var indexIdsInSnapshot = repositoryData.resolveIndices(indicesInSnapshot);
                    var snapshotIndexMetadataListener = new StepListener<Collection<IndexMetadata>>();
                    repository.getSnapshotIndexMetadata(snapshotId, indexIdsInSnapshot, snapshotIndexMetadataListener);
                    snapshotIndexMetadataListener.whenComplete(snapshotIndexMetadata -> {
                        for (IndexMetadata indexMetadata : snapshotIndexMetadata) {
                            metadataBuilder.put(indexMetadata, false);
                        }
                        final Metadata metadata = metadataBuilder.build();
                        // Apply renaming on index names, returning a map of names where
                        // the key is the renamed index and the value is the original name
                        final Map<String, String> indices = renamedIndices(request, indicesInSnapshot);
                        // Now we can start the actual restore process by adding shards to be recovered in the cluster state
                        // and updating cluster metadata (global and index) as needed
                        clusterService.submitStateUpdateTask("restore_snapshot[" + snapshotName + ']', new ClusterStateUpdateTask() {

                            final String restoreUUID = UUIDs.randomBase64UUID();

                            RestoreInfo restoreInfo = null;

                            @Override
                            public ClusterState execute(ClusterState currentState) {
                                RestoreInProgress restoreInProgress = currentState.custom(RestoreInProgress.TYPE);
                                // Check if the snapshot to restore is currently being deleted
                                SnapshotDeletionsInProgress deletionsInProgress = currentState.custom(SnapshotDeletionsInProgress.TYPE);
                                if (deletionsInProgress != null && deletionsInProgress.getEntries().stream().anyMatch(entry -> entry.getSnapshot().equals(snapshot))) {
                                    throw new ConcurrentSnapshotExecutionException(snapshot, "cannot restore a snapshot while a snapshot deletion is in-progress [" + deletionsInProgress.getEntries().get(0).getSnapshot() + "]");
                                }
                                // Updating cluster state
                                ClusterState.Builder builder = ClusterState.builder(currentState);
                                Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata());
                                ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
                                RoutingTable.Builder rtBuilder = RoutingTable.builder(currentState.routingTable());
                                ImmutableOpenMap<ShardId, RestoreInProgress.ShardRestoreStatus> shards;
                                Set<String> aliases = new HashSet<>();
                                if (indices.isEmpty() == false) {
                                    // We have some indices to restore
                                    ImmutableOpenMap.Builder<ShardId, RestoreInProgress.ShardRestoreStatus> shardsBuilder = ImmutableOpenMap.builder();
                                    final Version minIndexCompatibilityVersion = currentState.getNodes().getMaxNodeVersion().minimumIndexCompatibilityVersion();
                                    for (Map.Entry<String, String> indexEntry : indices.entrySet()) {
                                        String index = indexEntry.getValue();
                                        boolean partial = checkPartial(index);
                                        SnapshotRecoverySource recoverySource = new SnapshotRecoverySource(restoreUUID, snapshot, snapshotInfo.version(), index);
                                        String renamedIndexName = indexEntry.getKey();
                                        IndexMetadata snapshotIndexMetadata = metadata.index(index);
                                        snapshotIndexMetadata = updateIndexSettings(snapshotIndexMetadata, request.indexSettings(), request.ignoreIndexSettings());
                                        try {
                                            snapshotIndexMetadata = metadataIndexUpgradeService.upgradeIndexMetadata(snapshotIndexMetadata, minIndexCompatibilityVersion);
                                        } catch (Exception ex) {
                                            throw new SnapshotRestoreException(snapshot, "cannot restore index [" + index + "] because it cannot be upgraded", ex);
                                        }
                                        // Check that the index is closed or doesn't exist
                                        IndexMetadata currentIndexMetadata = currentState.metadata().index(renamedIndexName);
                                        IntSet ignoreShards = new IntHashSet();
                                        final Index renamedIndex;
                                        if (currentIndexMetadata == null) {
                                            // Index doesn't exist - create it and start recovery
                                            // Make sure that the index we are about to create has a validate name
                                            MetadataCreateIndexService.validateIndexName(renamedIndexName, currentState);
                                            createIndexService.validateIndexSettings(renamedIndexName, snapshotIndexMetadata.getSettings(), currentState, false);
                                            IndexMetadata.Builder indexMdBuilder = IndexMetadata.builder(snapshotIndexMetadata).state(IndexMetadata.State.OPEN).index(renamedIndexName);
                                            indexMdBuilder.settings(Settings.builder().put(snapshotIndexMetadata.getSettings()).put(IndexMetadata.SETTING_INDEX_UUID, UUIDs.randomBase64UUID()));
                                            shardLimitValidator.validateShardLimit(snapshotIndexMetadata.getSettings(), currentState);
                                            if (!request.includeAliases() && !snapshotIndexMetadata.getAliases().isEmpty()) {
                                                // Remove all aliases - they shouldn't be restored
                                                indexMdBuilder.removeAllAliases();
                                            } else {
                                                for (ObjectCursor<String> alias : snapshotIndexMetadata.getAliases().keys()) {
                                                    aliases.add(alias.value);
                                                }
                                            }
                                            IndexMetadata updatedIndexMetadata = indexMdBuilder.build();
                                            if (partial) {
                                                populateIgnoredShards(index, ignoreShards);
                                            }
                                            rtBuilder.addAsNewRestore(updatedIndexMetadata, recoverySource, ignoreShards);
                                            blocks.addBlocks(updatedIndexMetadata);
                                            mdBuilder.put(updatedIndexMetadata, true);
                                            renamedIndex = updatedIndexMetadata.getIndex();
                                        } else {
                                            validateExistingIndex(currentIndexMetadata, snapshotIndexMetadata, renamedIndexName, partial);
                                            // Index exists and it's closed - open it in metadata and start recovery
                                            IndexMetadata.Builder indexMdBuilder = IndexMetadata.builder(snapshotIndexMetadata).state(IndexMetadata.State.OPEN);
                                            indexMdBuilder.version(Math.max(snapshotIndexMetadata.getVersion(), 1 + currentIndexMetadata.getVersion()));
                                            indexMdBuilder.mappingVersion(Math.max(snapshotIndexMetadata.getMappingVersion(), 1 + currentIndexMetadata.getMappingVersion()));
                                            indexMdBuilder.settingsVersion(Math.max(snapshotIndexMetadata.getSettingsVersion(), 1 + currentIndexMetadata.getSettingsVersion()));
                                            for (int shard = 0; shard < snapshotIndexMetadata.getNumberOfShards(); shard++) {
                                                indexMdBuilder.primaryTerm(shard, Math.max(snapshotIndexMetadata.primaryTerm(shard), currentIndexMetadata.primaryTerm(shard)));
                                            }
                                            if (!request.includeAliases()) {
                                                // Remove all snapshot aliases
                                                if (!snapshotIndexMetadata.getAliases().isEmpty()) {
                                                    indexMdBuilder.removeAllAliases();
                                                }
                                                // Add existing aliases
                                                for (ObjectCursor<AliasMetadata> alias : currentIndexMetadata.getAliases().values()) {
                                                    indexMdBuilder.putAlias(alias.value);
                                                }
                                            } else {
                                                for (ObjectCursor<String> alias : snapshotIndexMetadata.getAliases().keys()) {
                                                    aliases.add(alias.value);
                                                }
                                            }
                                            indexMdBuilder.settings(Settings.builder().put(snapshotIndexMetadata.getSettings()).put(IndexMetadata.SETTING_INDEX_UUID, currentIndexMetadata.getIndexUUID()));
                                            IndexMetadata updatedIndexMetadata = indexMdBuilder.index(renamedIndexName).build();
                                            rtBuilder.addAsRestore(updatedIndexMetadata, recoverySource);
                                            blocks.updateBlocks(updatedIndexMetadata);
                                            mdBuilder.put(updatedIndexMetadata, true);
                                            renamedIndex = updatedIndexMetadata.getIndex();
                                        }
                                        for (int shard = 0; shard < snapshotIndexMetadata.getNumberOfShards(); shard++) {
                                            if (!ignoreShards.contains(shard)) {
                                                shardsBuilder.put(new ShardId(renamedIndex, shard), new RestoreInProgress.ShardRestoreStatus(clusterService.state().nodes().getLocalNodeId()));
                                            } else {
                                                shardsBuilder.put(new ShardId(renamedIndex, shard), new RestoreInProgress.ShardRestoreStatus(clusterService.state().nodes().getLocalNodeId(), RestoreInProgress.State.FAILURE));
                                            }
                                        }
                                    }
                                    shards = shardsBuilder.build();
                                    RestoreInProgress.Entry restoreEntry = new RestoreInProgress.Entry(restoreUUID, snapshot, overallState(RestoreInProgress.State.INIT, shards), List.copyOf(indices.keySet()), shards);
                                    RestoreInProgress.Builder restoreInProgressBuilder;
                                    if (restoreInProgress != null) {
                                        restoreInProgressBuilder = new RestoreInProgress.Builder(restoreInProgress);
                                    } else {
                                        restoreInProgressBuilder = new RestoreInProgress.Builder();
                                    }
                                    builder.putCustom(RestoreInProgress.TYPE, restoreInProgressBuilder.add(restoreEntry).build());
                                } else {
                                    shards = ImmutableOpenMap.of();
                                }
                                validateExistingTemplates();
                                checkAliasNameConflicts(indices, aliases);
                                // Restore templates (but do NOT overwrite existing templates)
                                restoreTemplates(mdBuilder, currentState);
                                // Restore global state if needed
                                if (request.includeGlobalSettings() && metadata.persistentSettings() != null) {
                                    Settings settings = metadata.persistentSettings();
                                    // CrateDB patch to only restore defined settings
                                    if (request.globalSettings().length > 0) {
                                        var filteredSettingBuilder = Settings.builder();
                                        for (String prefix : request.globalSettings()) {
                                            filteredSettingBuilder.put(settings.filter(s -> s.startsWith(prefix)));
                                        }
                                        settings = filteredSettingBuilder.build();
                                    }
                                    clusterSettings.validateUpdate(settings);
                                    mdBuilder.persistentSettings(settings);
                                }
                                if (request.includeCustomMetadata() && metadata.customs() != null) {
                                    // CrateDB patch to only restore defined custom metadata types
                                    List<String> customMetadataTypes = Arrays.asList(request.customMetadataTypes());
                                    boolean includeAll = customMetadataTypes.size() == 0;
                                    for (ObjectObjectCursor<String, Metadata.Custom> cursor : metadata.customs()) {
                                        if (!RepositoriesMetadata.TYPE.equals(cursor.key)) {
                                            if (includeAll || customMetadataTypes.contains(cursor.key)) {
                                                mdBuilder.putCustom(cursor.key, cursor.value);
                                            }
                                        }
                                    }
                                }
                                if (completed(shards)) {
                                    // We don't have any indices to restore - we are done
                                    restoreInfo = new RestoreInfo(snapshotId.getName(), Collections.unmodifiableList(new ArrayList<>(indices.keySet())), shards.size(), shards.size() - failedShards(shards));
                                }
                                RoutingTable rt = rtBuilder.build();
                                ClusterState updatedState = builder.metadata(mdBuilder).blocks(blocks).routingTable(rt).build();
                                return allocationService.reroute(updatedState, "restored snapshot [" + snapshot + "]");
                            }

                            private void checkAliasNameConflicts(Map<String, String> renamedIndices, Set<String> aliases) {
                                for (Map.Entry<String, String> renamedIndex : renamedIndices.entrySet()) {
                                    if (aliases.contains(renamedIndex.getKey())) {
                                        throw new SnapshotRestoreException(snapshot, "cannot rename index [" + renamedIndex.getValue() + "] into [" + renamedIndex.getKey() + "] because of conflict with an alias with the same name");
                                    }
                                }
                            }

                            private void populateIgnoredShards(String index, IntSet ignoreShards) {
                                for (SnapshotShardFailure failure : snapshotInfo.shardFailures()) {
                                    if (index.equals(failure.index())) {
                                        ignoreShards.add(failure.shardId());
                                    }
                                }
                            }

                            private boolean checkPartial(String index) {
                                // Make sure that index was fully snapshotted
                                if (failed(snapshotInfo, index)) {
                                    if (request.partial()) {
                                        return true;
                                    } else {
                                        throw new SnapshotRestoreException(snapshot, "index [" + index + "] wasn't fully snapshotted - cannot " + "restore");
                                    }
                                } else {
                                    return false;
                                }
                            }

                            private void validateExistingIndex(IndexMetadata currentIndexMetadata, IndexMetadata snapshotIndexMetadata, String renamedIndex, boolean partial) {
                                // Index exist - checking that it's closed
                                if (currentIndexMetadata.getState() != IndexMetadata.State.CLOSE) {
                                    // TODO: Enable restore for open indices
                                    throw new SnapshotRestoreException(snapshot, "cannot restore index [" + renamedIndex + "] because an open index " + "with same name already exists in the cluster. Either close or delete the existing index or restore the " + "index under a different name by providing a rename pattern and replacement name");
                                }
                                // Index exist - checking if it's partial restore
                                if (partial) {
                                    throw new SnapshotRestoreException(snapshot, "cannot restore partial index [" + renamedIndex + "] because such index already exists");
                                }
                                // Make sure that the number of shards is the same. That's the only thing that we cannot change
                                if (currentIndexMetadata.getNumberOfShards() != snapshotIndexMetadata.getNumberOfShards()) {
                                    throw new SnapshotRestoreException(snapshot, "cannot restore index [" + renamedIndex + "] with [" + currentIndexMetadata.getNumberOfShards() + "] shards from a snapshot of index [" + snapshotIndexMetadata.getIndex().getName() + "] with [" + snapshotIndexMetadata.getNumberOfShards() + "] shards");
                                }
                            }

                            /**
                             * Optionally updates index settings in indexMetadata by removing settings listed in ignoreSettings and
                             * merging them with settings in changeSettings.
                             */
                            private IndexMetadata updateIndexSettings(IndexMetadata indexMetadata, Settings changeSettings, String[] ignoreSettings) {
                                if (changeSettings.names().isEmpty() && ignoreSettings.length == 0) {
                                    return indexMetadata;
                                }
                                Settings normalizedChangeSettings = Settings.builder().put(changeSettings).normalizePrefix(IndexMetadata.INDEX_SETTING_PREFIX).build();
                                IndexMetadata.Builder builder = IndexMetadata.builder(indexMetadata);
                                Settings settings = indexMetadata.getSettings();
                                Set<String> keyFilters = new HashSet<>();
                                List<String> simpleMatchPatterns = new ArrayList<>();
                                for (String ignoredSetting : ignoreSettings) {
                                    if (!Regex.isSimpleMatchPattern(ignoredSetting)) {
                                        if (UNREMOVABLE_SETTINGS.contains(ignoredSetting)) {
                                            throw new SnapshotRestoreException(snapshot, "cannot remove setting [" + ignoredSetting + "] on restore");
                                        } else {
                                            keyFilters.add(ignoredSetting);
                                        }
                                    } else {
                                        simpleMatchPatterns.add(ignoredSetting);
                                    }
                                }
                                Predicate<String> settingsFilter = k -> {
                                    if (UNREMOVABLE_SETTINGS.contains(k) == false) {
                                        for (String filterKey : keyFilters) {
                                            if (k.equals(filterKey)) {
                                                return false;
                                            }
                                        }
                                        for (String pattern : simpleMatchPatterns) {
                                            if (Regex.simpleMatch(pattern, k)) {
                                                return false;
                                            }
                                        }
                                    }
                                    return true;
                                };
                                Settings.Builder settingsBuilder = Settings.builder().put(settings.filter(settingsFilter)).put(normalizedChangeSettings.filter(k -> {
                                    if (UNMODIFIABLE_SETTINGS.contains(k)) {
                                        throw new SnapshotRestoreException(snapshot, "cannot modify setting [" + k + "] on restore");
                                    } else {
                                        return true;
                                    }
                                }));
                                settingsBuilder.remove(IndexMetadata.VERIFIED_BEFORE_CLOSE_SETTING.getKey());
                                return builder.settings(settingsBuilder).build();
                            }

                            private void restoreTemplates(Metadata.Builder mdBuilder, ClusterState currentState) {
                                List<String> toRestore = Arrays.asList(request.templates());
                                if (metadata.templates() != null) {
                                    for (ObjectCursor<IndexTemplateMetadata> cursor : metadata.templates().values()) {
                                        if (currentState.metadata().templates().get(cursor.value.name()) == null && (request.allTemplates() || toRestore.contains(cursor.value.name()))) {
                                            mdBuilder.put(cursor.value);
                                        }
                                    }
                                }
                            }

                            private void validateExistingTemplates() {
                                if (request.indicesOptions().ignoreUnavailable() || request.allTemplates()) {
                                    return;
                                }
                                for (String template : request.templates()) {
                                    if (!metadata.templates().containsKey(template)) {
                                        throw new ResourceNotFoundException("[{}] template not found", template);
                                    }
                                }
                            }

                            @Override
                            public void onFailure(String source, Exception e) {
                                LOGGER.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot", snapshotId), e);
                                listener.onFailure(e);
                            }

                            @Override
                            public TimeValue timeout() {
                                return request.masterNodeTimeout();
                            }

                            @Override
                            public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
                                listener.onResponse(new RestoreCompletionResponse(restoreUUID, snapshot, restoreInfo));
                            }
                        });
                    }, listener::onFailure);
                }, listener::onFailure);
            }));
        }, listener::onFailure);
    } catch (Exception e) {
        LOGGER.warn(() -> new ParameterizedMessage("[{}] failed to restore snapshot", request.repositoryName + ":" + request.snapshotName), e);
        listener.onFailure(e);
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) MetadataIndexUpgradeService(org.elasticsearch.cluster.metadata.MetadataIndexUpgradeService) Arrays(java.util.Arrays) SETTING_AUTO_EXPAND_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS) ShardLimitValidator(org.elasticsearch.indices.ShardLimitValidator) SETTING_VERSION_CREATED(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_VERSION_CREATED) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) SnapshotRecoverySource(org.elasticsearch.cluster.routing.RecoverySource.SnapshotRecoverySource) AllocationService(org.elasticsearch.cluster.routing.allocation.AllocationService) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) ObjectObjectCursor(com.carrotsearch.hppc.cursors.ObjectObjectCursor) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) Settings(org.elasticsearch.common.settings.Settings) RestoreInProgress(org.elasticsearch.cluster.RestoreInProgress) Map(java.util.Map) IndicesOptions(org.elasticsearch.action.support.IndicesOptions) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) StepListener(org.elasticsearch.action.StepListener) Priority(org.elasticsearch.common.Priority) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) Predicate(java.util.function.Predicate) Collection(java.util.Collection) UUIDs(org.elasticsearch.common.UUIDs) Set(java.util.Set) ObjectCursor(com.carrotsearch.hppc.cursors.ObjectCursor) ClusterChangedEvent(org.elasticsearch.cluster.ClusterChangedEvent) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) RecoverySource(org.elasticsearch.cluster.routing.RecoverySource) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Version(org.elasticsearch.Version) TimeValue(io.crate.common.unit.TimeValue) Optional(java.util.Optional) SETTING_INDEX_UUID(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_INDEX_UUID) RepositoryData(org.elasticsearch.repositories.RepositoryData) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) SETTING_NUMBER_OF_SHARDS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_SHARDS) SETTING_VERSION_UPGRADED(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_VERSION_UPGRADED) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) ClusterService(org.elasticsearch.cluster.service.ClusterService) SnapshotUtils.filterIndices(org.elasticsearch.snapshots.SnapshotUtils.filterIndices) HashMap(java.util.HashMap) Index(org.elasticsearch.index.Index) Lucene(org.elasticsearch.common.lucene.Lucene) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Metadata(org.elasticsearch.cluster.metadata.Metadata) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) ClusterStateTaskListener(org.elasticsearch.cluster.ClusterStateTaskListener) SETTING_NUMBER_OF_REPLICAS(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS) IndexSettings(org.elasticsearch.index.IndexSettings) Regex(org.elasticsearch.common.regex.Regex) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) ClusterStateApplier(org.elasticsearch.cluster.ClusterStateApplier) Repository(org.elasticsearch.repositories.Repository) Collections.emptySet(java.util.Collections.emptySet) IndexShard(org.elasticsearch.index.shard.IndexShard) IntHashSet(com.carrotsearch.hppc.IntHashSet) IntSet(com.carrotsearch.hppc.IntSet) ClusterStateTaskConfig(org.elasticsearch.cluster.ClusterStateTaskConfig) SETTING_CREATION_DATE(org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_CREATION_DATE) ClusterStateTaskExecutor(org.elasticsearch.cluster.ClusterStateTaskExecutor) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) RoutingChangesObserver(org.elasticsearch.cluster.routing.RoutingChangesObserver) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) RepositoriesService(org.elasticsearch.repositories.RepositoriesService) MetadataCreateIndexService(org.elasticsearch.cluster.metadata.MetadataCreateIndexService) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) Collections.unmodifiableSet(java.util.Collections.unmodifiableSet) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) LogManager(org.apache.logging.log4j.LogManager) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) IntHashSet(com.carrotsearch.hppc.IntHashSet) ArrayList(java.util.ArrayList) Index(org.elasticsearch.index.Index) SnapshotDeletionsInProgress(org.elasticsearch.cluster.SnapshotDeletionsInProgress) Version(org.elasticsearch.Version) List(java.util.List) ArrayList(java.util.ArrayList) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) Settings(org.elasticsearch.common.settings.Settings) IndexSettings(org.elasticsearch.index.IndexSettings) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) HashSet(java.util.HashSet) IntHashSet(com.carrotsearch.hppc.IntHashSet) ClusterState(org.elasticsearch.cluster.ClusterState) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) RestoreInProgress(org.elasticsearch.cluster.RestoreInProgress) SnapshotRecoverySource(org.elasticsearch.cluster.routing.RecoverySource.SnapshotRecoverySource) RoutingTable(org.elasticsearch.cluster.routing.RoutingTable) Collection(java.util.Collection) Map(java.util.Map) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) HashMap(java.util.HashMap) Set(java.util.Set) HashSet(java.util.HashSet) Collections.emptySet(java.util.Collections.emptySet) IntHashSet(com.carrotsearch.hppc.IntHashSet) IntSet(com.carrotsearch.hppc.IntSet) Collections.unmodifiableSet(java.util.Collections.unmodifiableSet) IntSet(com.carrotsearch.hppc.IntSet) IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) RepositoriesMetadata(org.elasticsearch.cluster.metadata.RepositoriesMetadata) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) ImmutableOpenMap(org.elasticsearch.common.collect.ImmutableOpenMap) ShardId(org.elasticsearch.index.shard.ShardId) AliasMetadata(org.elasticsearch.cluster.metadata.AliasMetadata) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) IndexTemplateMetadata(org.elasticsearch.cluster.metadata.IndexTemplateMetadata) ClusterStateUpdateTask(org.elasticsearch.cluster.ClusterStateUpdateTask) ResourceNotFoundException(org.elasticsearch.ResourceNotFoundException) RepositoryData(org.elasticsearch.repositories.RepositoryData) Repository(org.elasticsearch.repositories.Repository) ShardRestoreStatus(org.elasticsearch.cluster.RestoreInProgress.ShardRestoreStatus) StepListener(org.elasticsearch.action.StepListener) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage)

Aggregations

AliasMetaData (org.elasticsearch.cluster.metadata.AliasMetaData)20 List (java.util.List)13 Settings (org.elasticsearch.common.settings.Settings)10 ArrayList (java.util.ArrayList)9 ImmutableOpenMap (org.elasticsearch.common.collect.ImmutableOpenMap)8 ObjectObjectCursor (com.carrotsearch.hppc.cursors.ObjectObjectCursor)5 IOException (java.io.IOException)5 HashMap (java.util.HashMap)5 Map (java.util.Map)5 Set (java.util.Set)5 IndicesOptions (org.elasticsearch.action.support.IndicesOptions)4 IndexTemplateMetaData (org.elasticsearch.cluster.metadata.IndexTemplateMetaData)4 Index (org.elasticsearch.index.Index)4 Arrays (java.util.Arrays)3 Collections (java.util.Collections)3 Optional (java.util.Optional)3 Collectors (java.util.stream.Collectors)3 GetAliasesResponse (org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse)3 AliasMetadata (org.elasticsearch.cluster.metadata.AliasMetadata)3 IndexMetaData (org.elasticsearch.cluster.metadata.IndexMetaData)3