Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
package org.elasticsearch.xpack.core.ilm;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.xpack.core.searchablesnapshots.MountSearchableSnapshotAction;
import org.elasticsearch.xpack.core.searchablesnapshots.MountSearchableSnapshotRequest;
import java.util.Objects;
import static org.elasticsearch.xpack.core.ilm.LifecycleExecutionState.fromIndexMetadata;
/**
* Restores the snapshot created for the designated index via the ILM policy to an index named using the provided prefix appended to the
* designated index name.
*/
public class MountSnapshotStep extends AsyncRetryDuringSnapshotActionStep {
public static final String NAME = "mount-snapshot";
private static final Logger logger = LogManager.getLogger(MountSnapshotStep.class);
private final String restoredIndexPrefix;
private final MountSearchableSnapshotRequest.Storage storageType;
public MountSnapshotStep(StepKey key, StepKey nextStepKey, Client client, String restoredIndexPrefix,
MountSearchableSnapshotRequest.Storage storageType) {
super(key, nextStepKey, client);
this.restoredIndexPrefix = restoredIndexPrefix;
this.storageType = Objects.requireNonNull(storageType, "a storage type must be specified");
}
@Override
public boolean isRetryable() {
return true;
}
public String getRestoredIndexPrefix() {
return restoredIndexPrefix;
}
public MountSearchableSnapshotRequest.Storage getStorage() {
return storageType;
}
@Override
void performDuringNoSnapshot(IndexMetadata indexMetadata, ClusterState currentClusterState, Listener listener) {
String indexName = indexMetadata.getIndex().getName();
LifecycleExecutionState lifecycleState = fromIndexMetadata(indexMetadata);
String policyName = indexMetadata.getSettings().get(LifecycleSettings.LIFECYCLE_NAME);
final String snapshotRepository = lifecycleState.getSnapshotRepository();
if (Strings.hasText(snapshotRepository) == false) {
listener.onFailure(new IllegalStateException("snapshot repository is not present for policy [" + policyName + "] and index [" +
indexName + "]"));
return;
}
final String snapshotName = lifecycleState.getSnapshotName();
if (Strings.hasText(snapshotName) == false) {
listener.onFailure(
new IllegalStateException("snapshot name was not generated for policy [" + policyName + "] and index [" + indexName + "]"));
return;
}
String mountedIndexName = restoredIndexPrefix + indexName;
if (currentClusterState.metadata().index(mountedIndexName) != null) {
logger.debug("mounted index [{}] for policy [{}] and index [{}] already exists. will not attempt to mount the index again",
mountedIndexName, policyName, indexName);
listener.onResponse(true);
return;
}
final String snapshotIndexName = lifecycleState.getSnapshotIndexName();
if (snapshotIndexName == null) {
// This index had its searchable snapshot created prior to a version where we captured
// the original index name, so make our best guess at the name
indexName = bestEffortIndexNameResolution(indexName);
logger.debug("index [{}] using policy [{}] does not have a stored snapshot index name, " +
"using our best effort guess of [{}] for the original snapshotted index name",
indexMetadata.getIndex().getName(), policyName, indexName);
} else {
// Use the name of the snapshot as specified in the metadata, because the current index
// name not might not reflect the name of the index actually in the snapshot
logger.debug("index [{}] using policy [{}] has a different name [{}] within the snapshot to be restored, " +
"using the snapshot index name from generated metadata for mounting", indexName, policyName, snapshotIndexName);
indexName = snapshotIndexName;
}
final MountSearchableSnapshotRequest mountSearchableSnapshotRequest = new MountSearchableSnapshotRequest(mountedIndexName,
snapshotRepository, snapshotName, indexName, Settings.builder()
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString())
.build(),
// we captured the index metadata when we took the snapshot. the index likely had the ILM execution state in the metadata.
// if we were to restore the lifecycle.name setting, the restored index would be captured by the ILM runner and,
// depending on what ILM execution state was captured at snapshot time, make it's way forward from _that_ step forward in
// the ILM policy.
// we'll re-set this setting on the restored index at a later step once we restored a deterministic execution state
new String[]{LifecycleSettings.LIFECYCLE_NAME},
// we'll not wait for the snapshot to complete in this step as the async steps are executed from threads that shouldn't
// perform expensive operations (ie. clusterStateProcessed)
false,
storageType);
getClient().execute(MountSearchableSnapshotAction.INSTANCE, mountSearchableSnapshotRequest,
ActionListener.wrap(response -> {
if (response.status() != RestStatus.OK && response.status() != RestStatus.ACCEPTED) {
logger.debug("mount snapshot response failed to complete");
throw new ElasticsearchException("mount snapshot response failed to complete, got response " + response.status());
}
listener.onResponse(true);
}, listener::onFailure));
}
/**
* Tries to guess the original index name given the current index name, tries to drop the
* "partial-" and "restored-" prefixes, since those are what ILM uses. Does not handle
* unorthodox cases like "restored-partial-[indexname]" since this is not intended to be
* exhaustive.
*/
static String bestEffortIndexNameResolution(String indexName) {
String originalName = indexName.replaceFirst("^" + SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX, "");
originalName = originalName.replaceFirst("^" + SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX, "");
return originalName;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), restoredIndexPrefix, storageType);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MountSnapshotStep other = (MountSnapshotStep) obj;
return super.equals(obj) &&
Objects.equals(restoredIndexPrefix, other.restoredIndexPrefix) &&
Objects.equals(storageType, other.storageType);
}
}