mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-16 09:54:55 +00:00
Plugins: Installation failed when bin/ and plugins/ directories are on different filesystems
Plugin installation failed when bin/, conf/ and plugins/ directories are on different file systems. The method File.move() can't be used to move a non-empty directory between different filesystems. I didn't find a simple way to unittest that, even with in-memory filesystems like jimfs or the Lucene test framework. Closes #8999
This commit is contained in:
parent
9f6a6a832f
commit
a5127d2ffd
@ -20,7 +20,6 @@
|
|||||||
package org.elasticsearch.common.io;
|
package org.elasticsearch.common.io;
|
||||||
|
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
|
|
||||||
@ -33,7 +32,6 @@ import java.nio.charset.Charset;
|
|||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import static java.nio.file.FileVisitResult.CONTINUE;
|
import static java.nio.file.FileVisitResult.CONTINUE;
|
||||||
@ -185,7 +183,7 @@ public final class FileSystemUtils {
|
|||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
// We just move the structure to new dir
|
// We just move the structure to new dir
|
||||||
// we can't do atomic move here since src / dest might be on different mounts?
|
// we can't do atomic move here since src / dest might be on different mounts?
|
||||||
Files.move(dir, path);
|
move(dir, path);
|
||||||
// We just ignore sub files from here
|
// We just ignore sub files from here
|
||||||
return FileVisitResult.SKIP_SUBTREE;
|
return FileVisitResult.SKIP_SUBTREE;
|
||||||
}
|
}
|
||||||
@ -224,16 +222,34 @@ public final class FileSystemUtils {
|
|||||||
* @param destination destination dir
|
* @param destination destination dir
|
||||||
*/
|
*/
|
||||||
public static void copyDirectoryRecursively(Path source, Path destination) throws IOException {
|
public static void copyDirectoryRecursively(Path source, Path destination) throws IOException {
|
||||||
Files.walkFileTree(source, new TreeCopier(source, destination));
|
Files.walkFileTree(source, new TreeCopier(source, destination, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move or rename a file to a target file. This method supports moving a file from
|
||||||
|
* different filesystems (not supported by Files.move()).
|
||||||
|
*
|
||||||
|
* @param source source file
|
||||||
|
* @param destination destination file
|
||||||
|
*/
|
||||||
|
public static void move(Path source, Path destination) throws IOException {
|
||||||
|
try {
|
||||||
|
// We can't use atomic move here since source & target can be on different filesystems.
|
||||||
|
Files.move(source, destination);
|
||||||
|
} catch (DirectoryNotEmptyException e) {
|
||||||
|
Files.walkFileTree(source, new TreeCopier(source, destination, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TreeCopier extends SimpleFileVisitor<Path> {
|
static class TreeCopier extends SimpleFileVisitor<Path> {
|
||||||
private final Path source;
|
private final Path source;
|
||||||
private final Path target;
|
private final Path target;
|
||||||
|
private final boolean delete;
|
||||||
|
|
||||||
TreeCopier(Path source, Path target) {
|
TreeCopier(Path source, Path target, boolean delete) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.delete = delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -249,11 +265,22 @@ public final class FileSystemUtils {
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||||
|
if (delete) {
|
||||||
|
IOUtils.rm(dir);
|
||||||
|
}
|
||||||
|
return CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
Path newFile = target.resolve(source.relativize(file));
|
Path newFile = target.resolve(source.relativize(file));
|
||||||
try {
|
try {
|
||||||
Files.copy(file, newFile);
|
Files.copy(file, newFile);
|
||||||
|
if ((delete) && (Files.exists(newFile))) {
|
||||||
|
Files.delete(file);
|
||||||
|
}
|
||||||
} catch (IOException x) {
|
} catch (IOException x) {
|
||||||
// We ignore this
|
// We ignore this
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,11 @@ public class PluginManager {
|
|||||||
if (Files.exists(toLocation)) {
|
if (Files.exists(toLocation)) {
|
||||||
IOUtils.rm(toLocation);
|
IOUtils.rm(toLocation);
|
||||||
}
|
}
|
||||||
Files.move(binFile, toLocation);
|
try {
|
||||||
|
FileSystemUtils.move(binFile, toLocation);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IOException("Could not move [" + binFile + "] to [" + toLocation + "]", e);
|
||||||
|
}
|
||||||
if (Files.getFileStore(toLocation).supportsFileAttributeView(PosixFileAttributeView.class)) {
|
if (Files.getFileStore(toLocation).supportsFileAttributeView(PosixFileAttributeView.class)) {
|
||||||
final Set<PosixFilePermission> perms = new HashSet<>();
|
final Set<PosixFilePermission> perms = new HashSet<>();
|
||||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user