3535import org .elasticsearch .cluster .metadata .IndexMetaData ;
3636import org .elasticsearch .cluster .node .DiscoveryNode ;
3737import org .elasticsearch .common .CheckedFunction ;
38+ import org .elasticsearch .common .CheckedRunnable ;
3839import org .elasticsearch .common .Randomness ;
3940import org .elasticsearch .common .SuppressForbidden ;
4041import org .elasticsearch .common .UUIDs ;
4546import org .elasticsearch .common .settings .Settings ;
4647import org .elasticsearch .common .unit .ByteSizeValue ;
4748import org .elasticsearch .common .unit .TimeValue ;
49+ import org .elasticsearch .common .util .set .Sets ;
4850import org .elasticsearch .common .xcontent .NamedXContentRegistry ;
4951import org .elasticsearch .core .internal .io .IOUtils ;
5052import org .elasticsearch .gateway .MetaDataStateFormat ;
@@ -285,7 +287,7 @@ public NodeEnvironment(Settings settings, Environment environment) throws IOExce
285287 ensureAtomicMoveSupported (nodePaths );
286288 }
287289
288- if (upgradeLegacyNodeFolders (logger , environment , nodeLock )) {
290+ if (upgradeLegacyNodeFolders (logger , settings , environment , nodeLock )) {
289291 assertCanWrite ();
290292 }
291293
@@ -311,7 +313,8 @@ public NodeEnvironment(Settings settings, Environment environment) throws IOExce
311313 * Upgrades all data paths that have been written to by an older ES version to the 8.0+ compatible folder layout,
312314 * removing the "nodes/${lockId}" folder prefix
313315 */
314- private static boolean upgradeLegacyNodeFolders (Logger logger , Environment environment , NodeLock nodeLock ) throws IOException {
316+ private static boolean upgradeLegacyNodeFolders (Logger logger , Settings settings , Environment environment ,
317+ NodeLock nodeLock ) throws IOException {
315318 boolean upgradeNeeded = false ;
316319
317320 // check if we can do an auto-upgrade
@@ -334,8 +337,10 @@ private static boolean upgradeLegacyNodeFolders(Logger logger, Environment envir
334337 upgradeNeeded = true ;
335338
336339 if (nodeLockIds .equals (Arrays .asList (0 )) == false ) {
337- throw new IllegalStateException ("Cannot upgrade multiple path with multiple lock ids or lock id different to 0 " +
338- "(path: " + nodesFolderPath + " ids: " + nodeLockIds + ")" );
340+ throw new IllegalStateException ("data path " + nodesFolderPath + " cannot be upgraded automatically because it " +
341+ "contains data from nodes with ordinals " + nodeLockIds + ", due to previous use of the now obsolete " +
342+ "[node.max_local_storage_nodes] setting. Please check the breaking changes docs for the current version of " +
343+ "Elasticsearch to find an upgrade path" );
339344 }
340345 }
341346 }
@@ -364,6 +369,7 @@ private static boolean upgradeLegacyNodeFolders(Logger logger, Environment envir
364369 // move contents from legacy path to new path
365370 assert nodeLock .getNodePaths ().length == legacyNodeLock .getNodePaths ().length ;
366371 try {
372+ final List <CheckedRunnable <IOException >> upgradeActions = new ArrayList <>();
367373 for (int i = 0 ; i < legacyNodeLock .getNodePaths ().length ; i ++) {
368374 final NodePath legacyNodePath = legacyNodeLock .getNodePaths ()[i ];
369375 final NodePath nodePath = nodeLock .getNodePaths ()[i ];
@@ -396,14 +402,24 @@ private static boolean upgradeLegacyNodeFolders(Logger logger, Environment envir
396402 }
397403 }
398404
399- // now do the actual move
400- for (String folderName : folderNames ) {
401- final Path sourceSubFolderPath = legacyNodePath .path .resolve (folderName );
402- final Path targetSubFolderPath = nodePath .path .resolve (folderName );
403- Files .move (sourceSubFolderPath , targetSubFolderPath , StandardCopyOption .ATOMIC_MOVE );
404- logger .info ("data folder upgrade: moved from [{}] to [{}]" , sourceSubFolderPath , targetSubFolderPath );
405- }
406- IOUtils .fsync (nodePath .path , true );
405+ assert Sets .difference (Sets .newHashSet (INDICES_FOLDER , MetaDataStateFormat .STATE_DIR_NAME ), folderNames ).isEmpty () :
406+ "expected indices and/or state dir folder but was " + folderNames ;
407+
408+ upgradeActions .add (() -> {
409+ for (String folderName : folderNames ) {
410+ final Path sourceSubFolderPath = legacyNodePath .path .resolve (folderName );
411+ final Path targetSubFolderPath = nodePath .path .resolve (folderName );
412+ Files .move (sourceSubFolderPath , targetSubFolderPath , StandardCopyOption .ATOMIC_MOVE );
413+ logger .info ("data folder upgrade: moved from [{}] to [{}]" , sourceSubFolderPath , targetSubFolderPath );
414+ }
415+ IOUtils .fsync (nodePath .path , true );
416+ });
417+ }
418+ // now do the actual upgrade. start by upgrading the node metadata file before moving anything, since a downgrade in an
419+ // intermediate state would be pretty disastrous
420+ loadOrCreateNodeMetaData (settings , logger , legacyNodeLock .getNodePaths ());
421+ for (CheckedRunnable <IOException > upgradeAction : upgradeActions ) {
422+ upgradeAction .run ();
407423 }
408424 } finally {
409425 legacyNodeLock .close ();
0 commit comments