Skip to content

Require manifest file for upgrades to v8 #52412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.cluster.metadata.IndexGraveyard;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.Manifest;
import org.elasticsearch.cluster.metadata.MetaData;
Expand All @@ -33,9 +33,10 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

/**
Expand Down Expand Up @@ -71,7 +72,27 @@ public MetaStateService(NodeEnvironment nodeEnv, NamedXContentRegistry namedXCon
public Tuple<Manifest, MetaData> loadFullState() throws IOException {
final Manifest manifest = MANIFEST_FORMAT.loadLatestState(logger, namedXContentRegistry, nodeEnv.nodeDataPaths());
if (manifest == null) {
return loadFullStateBWC();
if (META_DATA_FORMAT.loadLatestState(logger, namedXContentRegistry, nodeEnv.nodeDataPaths()) != null) {
// not mentioning version constants explicitly since we already assert that this code is dead from v9 onwards
throw new IllegalStateException("found on-disk global metadata from a cluster of version 6.x or earlier; you must first " +
"upgrade this node to a 7.x version before you can upgrade it to version " + Version.CURRENT);
}
final Set<Index> indices = new HashSet<>();
for (String indexFolder : nodeEnv.availableIndexFolders()) {
final IndexMetaData indexMetadata
= INDEX_META_DATA_FORMAT.loadLatestState(logger, namedXContentRegistry, nodeEnv.resolveIndexFolder(indexFolder));
if (indexMetadata != null) {
indices.add(indexMetadata.getIndex());
}
}

if (indices.isEmpty() == false) {
// not mentioning version constants explicitly since we already assert that this code is dead from v9 onwards
throw new IllegalStateException("found on-disk index metadata from a cluster of version 6.x or earlier for indices " +
indices + "; you must first upgrade this node to a 7.x version before you can upgrade it to version " +
Version.CURRENT);
}
return Tuple.tuple(Manifest.empty(), MetaData.builder().build());
}

final MetaData.Builder metaDataBuilder;
Expand Down Expand Up @@ -104,54 +125,6 @@ public Tuple<Manifest, MetaData> loadFullState() throws IOException {
return new Tuple<>(manifest, metaDataBuilder.build());
}

/**
* "Manifest-less" BWC version of loading metadata from disk. See also {@link #loadFullState()}
*/
private Tuple<Manifest, MetaData> loadFullStateBWC() throws IOException {
Map<Index, Long> indices = new HashMap<>();
MetaData.Builder metaDataBuilder;

Tuple<MetaData, Long> metaDataAndGeneration =
META_DATA_FORMAT.loadLatestStateWithGeneration(logger, namedXContentRegistry, nodeEnv.nodeDataPaths());
MetaData globalMetaData = metaDataAndGeneration.v1();
long globalStateGeneration = metaDataAndGeneration.v2();

final IndexGraveyard indexGraveyard;
if (globalMetaData != null) {
metaDataBuilder = MetaData.builder(globalMetaData);
indexGraveyard = globalMetaData.custom(IndexGraveyard.TYPE);
// TODO https://github.com/elastic/elasticsearch/issues/38556
// assert Version.CURRENT.major < 8 : "failed to find manifest file, which is mandatory staring with Elasticsearch version 8.0";
} else {
metaDataBuilder = MetaData.builder();
indexGraveyard = IndexGraveyard.builder().build();
}

for (String indexFolderName : nodeEnv.availableIndexFolders()) {
Tuple<IndexMetaData, Long> indexMetaDataAndGeneration =
INDEX_META_DATA_FORMAT.loadLatestStateWithGeneration(logger, namedXContentRegistry,
nodeEnv.resolveIndexFolder(indexFolderName));
// TODO https://github.com/elastic/elasticsearch/issues/38556
// assert Version.CURRENT.major < 8 : "failed to find manifest file, which is mandatory staring with Elasticsearch version 8.0";
IndexMetaData indexMetaData = indexMetaDataAndGeneration.v1();
long generation = indexMetaDataAndGeneration.v2();
if (indexMetaData != null) {
if (indexGraveyard.containsIndex(indexMetaData.getIndex())) {
logger.debug("[{}] found metadata for deleted index [{}]", indexFolderName, indexMetaData.getIndex());
// this index folder is cleared up when state is recovered
} else {
indices.put(indexMetaData.getIndex(), generation);
metaDataBuilder.put(indexMetaData, false);
}
} else {
logger.debug("[{}] failed to find metadata for existing index location", indexFolderName);
}
}

Manifest manifest = Manifest.unknownCurrentTermAndVersion(globalStateGeneration, indices);
return new Tuple<>(manifest, metaDataBuilder.build());
}

/**
* Loads the index state for the provided index name, returning null if doesn't exists.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,44 +506,6 @@ public void testArchiveBrokenClusterSettings() throws Exception {
assertHitCount(client().prepareSearch().setQuery(matchAllQuery()).get(), 1L);
}

@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/48701")
// This test relates to loading a broken state that was written by a 6.x node, but for now we do not load state from old nodes.
public void testHalfDeletedIndexImport() throws Exception {
// It's possible for a 6.x node to add a tombstone for an index but not actually delete the index metadata from disk since that
// deletion is slightly deferred and may race against the node being shut down; if you upgrade to 7.x when in this state then the
// node won't start.

internalCluster().startNode();
createIndex("test", Settings.builder()
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.build());
ensureGreen("test");

final MetaData metaData = internalCluster().getInstance(ClusterService.class).state().metaData();
final Path[] paths = internalCluster().getInstance(NodeEnvironment.class).nodeDataPaths();
// writeBrokenMeta(metaStateService -> {
// metaStateService.writeGlobalState("test", MetaData.builder(metaData)
// // we remove the manifest file, resetting the term and making this look like an upgrade from 6.x, so must also reset the
// // term in the coordination metadata
// .coordinationMetaData(CoordinationMetaData.builder(metaData.coordinationMetaData()).term(0L).build())
// // add a tombstone but do not delete the index metadata from disk
// .putCustom(IndexGraveyard.TYPE, IndexGraveyard.builder().addTombstone(metaData.index("test").getIndex()).build()).build());
// for (final Path path : paths) {
// try (Stream<Path> stateFiles = Files.list(path.resolve(MetaDataStateFormat.STATE_DIR_NAME))) {
// for (final Path manifestPath : stateFiles
// .filter(p -> p.getFileName().toString().startsWith(Manifest.FORMAT.getPrefix())).collect(Collectors.toList())) {
// IOUtils.rm(manifestPath);
// }
// }
// }
// });

ensureGreen();

assertBusy(() -> assertThat(internalCluster().getInstance(NodeEnvironment.class).availableIndexFolders(), empty()));
}

private void restartNodesOnBrokenClusterState(ClusterState.Builder clusterStateBuilder) throws Exception {
Map<String, PersistedClusterStateService> lucenePersistedStateFactories = Stream.of(internalCluster().getNodeNames())
.collect(Collectors.toMap(Function.identity(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
import java.io.IOException;
import java.util.HashMap;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.nullValue;

public class MetaStateServiceTests extends ESTestCase {
Expand Down Expand Up @@ -95,26 +96,26 @@ public void testWriteGlobalStateWithIndexAndNoIndexIsLoaded() throws Exception {
assertThat(metaStateService.loadGlobalState().hasIndex("test1"), equalTo(false));
}

public void testLoadFullStateBWC() throws Exception {
IndexMetaData indexMetaData = indexMetaData("test1");
public void testLoadFullStateRejectsGlobalMetadataWithoutManifest() throws Exception {
MetaData metaData = MetaData.builder()
.persistentSettings(Settings.builder().put("test1", "value1").build())
.put(indexMetaData, true)
.build();
.persistentSettings(Settings.builder().put("test1", "value1").build())
.build();

long globalGeneration = metaStateService.writeGlobalState("test_write", metaData);
long indexGeneration = metaStateService.writeIndex("test_write", indexMetaData);
metaStateService.writeGlobalState("test_write", metaData);

Tuple<Manifest, MetaData> manifestAndMetaData = metaStateService.loadFullState();
Manifest manifest = manifestAndMetaData.v1();
assertThat(manifest.getGlobalGeneration(), equalTo(globalGeneration));
assertThat(manifest.getIndexGenerations(), hasKey(indexMetaData.getIndex()));
assertThat(manifest.getIndexGenerations().get(indexMetaData.getIndex()), equalTo(indexGeneration));
assertThat(expectThrows(IllegalStateException.class, metaStateService::loadFullState).getMessage(),
containsString("found on-disk global metadata from a cluster of version 6.x or earlier; you must first upgrade this node to " +
"a 7.x version before you can upgrade it to version " + Version.CURRENT));
}

MetaData loadedMetaData = manifestAndMetaData.v2();
assertThat(loadedMetaData.persistentSettings(), equalTo(metaData.persistentSettings()));
assertThat(loadedMetaData.hasIndex("test1"), equalTo(true));
assertThat(loadedMetaData.index("test1"), equalTo(indexMetaData));
public void testLoadFullStateRejectsIndexMetadataWithoutManifest() throws Exception {
IndexMetaData indexMetaData = indexMetaData("test1");
metaStateService.writeIndex("test_write", indexMetaData);

assertThat(expectThrows(IllegalStateException.class, metaStateService::loadFullState).getMessage(), allOf(
containsString("found on-disk index metadata from a cluster of version 6.x or earlier for indices ["),
containsString(indexMetaData.getIndex().toString()),
containsString("you must first upgrade this node to a 7.x version before you can upgrade it to version " + Version.CURRENT)));
}

public void testLoadEmptyStateNoManifest() throws IOException {
Expand Down