From 60e1ca3dfb2c2cacd45c851e9547085c16cf9db4 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Thu, 14 Nov 2024 14:14:51 +0100 Subject: [PATCH] Empty dir error in datanode inplace migration (#20912) * Empty dir error in datanode inplace migration * better place for empty data dir compatibility check * added changelog * compatibility warning for inplace migration in case of empty data dir * display warning * rephrased empty datadir warning * only show green alert when there are no warnings --------- Co-authored-by: Mohamed Ould Hocine Co-authored-by: Matthias Oesterheld <33032967+moesterheld@users.noreply.github.com> --- changelog/unreleased/pr-20912.toml | 5 +++ .../datanode/rest/CompatibilityResult.java | 3 +- .../rest/IndicesDirectoryController.java | 13 +++++- .../src/components/datanode/Types.ts | 2 + .../CompatibilityCheckStep.test.tsx | 2 + .../migrations/CompatibilityCheckStep.tsx | 44 ++++++++++++------- 6 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 changelog/unreleased/pr-20912.toml diff --git a/changelog/unreleased/pr-20912.toml b/changelog/unreleased/pr-20912.toml new file mode 100644 index 000000000000..83bdc2b6892c --- /dev/null +++ b/changelog/unreleased/pr-20912.toml @@ -0,0 +1,5 @@ +type = "fixed" +message = "Directory compatibility check for datanode inplace migration rejects empty dir" + +issues = [] +pulls = ["20912"] diff --git a/data-node/src/main/java/org/graylog/datanode/rest/CompatibilityResult.java b/data-node/src/main/java/org/graylog/datanode/rest/CompatibilityResult.java index cb3b4e4839d3..fb86465782a8 100644 --- a/data-node/src/main/java/org/graylog/datanode/rest/CompatibilityResult.java +++ b/data-node/src/main/java/org/graylog/datanode/rest/CompatibilityResult.java @@ -20,5 +20,6 @@ public record CompatibilityResult(String hostname, String opensearchVersion, IndexerDirectoryInformation info, - java.util.List compatibilityErrors) { + java.util.List compatibilityErrors, + java.util.List compatibilityWarnings) { } diff --git a/data-node/src/main/java/org/graylog/datanode/rest/IndicesDirectoryController.java b/data-node/src/main/java/org/graylog/datanode/rest/IndicesDirectoryController.java index 5445b5d95dd7..c9c758c4ae71 100644 --- a/data-node/src/main/java/org/graylog/datanode/rest/IndicesDirectoryController.java +++ b/data-node/src/main/java/org/graylog/datanode/rest/IndicesDirectoryController.java @@ -29,6 +29,7 @@ import org.graylog.datanode.filesystem.index.dto.NodeInformation; import org.graylog.shaded.opensearch2.org.opensearch.Version; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -59,13 +60,21 @@ public CompatibilityResult status() { directoryReadableValidator.validate(dataTargetDir.toUri().toString(), dataTargetDir); final IndexerDirectoryInformation info = indicesDirectoryParser.parse(dataTargetDir); final Version currentVersion = Version.fromString(opensearchVersion); + + final List compatibilityWarnings = new ArrayList<>(); + + if (info.nodes().isEmpty() || info.nodes().stream().allMatch(n -> n.indices().isEmpty())) { + compatibilityWarnings.add("Your configured opensearch_data_location directory " + dataTargetDir.toAbsolutePath() + " doesn't contain any indices! Do you want to continue without migrating existing data?"); + } + final List compatibilityErrors = info.nodes().stream() .filter(node -> !isNodeCompatible(node, currentVersion)) .map(node -> String.format(Locale.ROOT, "Current version %s of Opensearch is not compatible with index version %s", currentVersion, node.nodeVersion())) .toList(); - return new CompatibilityResult(hostname, opensearchVersion, info, compatibilityErrors); + + return new CompatibilityResult(hostname, opensearchVersion, info, compatibilityErrors, compatibilityWarnings); } catch (Exception e) { - return new CompatibilityResult(hostname, opensearchVersion, new IndexerDirectoryInformation(dataTargetDir, Collections.emptyList()), Collections.singletonList(e.getMessage())); + return new CompatibilityResult(hostname, opensearchVersion, new IndexerDirectoryInformation(dataTargetDir, Collections.emptyList()), Collections.singletonList(e.getMessage()), Collections.emptyList()); } } diff --git a/graylog2-web-interface/src/components/datanode/Types.ts b/graylog2-web-interface/src/components/datanode/Types.ts index 937d12d90465..202a4e708962 100644 --- a/graylog2-web-interface/src/components/datanode/Types.ts +++ b/graylog2-web-interface/src/components/datanode/Types.ts @@ -36,12 +36,14 @@ export type NodeInfo = { node_version: string, } export type CompatibilityResponseType = { + hostname: string, opensearch_version: string, info: { nodes: Array, opensearch_data_location: string, }, compatibility_errors: Array, + compatibility_warnings: Array, }; export type DataNode = { hostname: string, diff --git a/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.test.tsx b/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.test.tsx index ee4a696e7993..6d6f574df23b 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.test.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.test.tsx @@ -68,9 +68,11 @@ describe('CompatibilityCheckStep', () => { asMock(useCompatibilityCheck).mockReturnValue({ data: { datanode1: { + hostname: 'hostname1', opensearch_version: '2.10.0', info: null, compatibility_errors: ['org.graylog.shaded.opensearch2.org.apache.lucene.index.IndexFormatTooOldException: Format version is not supported (resource BufferedChecksumIndexInput(ByteBufferIndexInput(path="/index/segments_3"))): This index was initially created with Lucene 7.x while the current version is 9.7.0 and Lucene only supports reading the current and previous major versions. This version of Lucene only supports indexes created with release 8.0 and later by default.'], + compatibility_warnings: ['warnings'], }, }, refetch: () => {}, diff --git a/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.tsx b/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.tsx index 12c3eab3d401..592040c4d602 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/CompatibilityCheckStep.tsx @@ -37,27 +37,39 @@ const CompatibilityCheckStep = ({ currentStep, onTriggerStep, hideActions }: Mig } const errors = Object.values(data || {}).flatMap((value) => (value?.compatibility_errors || [])); + const warnings = Object.values(data || {}).flatMap((value) => (value?.compatibility_warnings || [])); const isCompatible = errors.length === 0; return ( <>

Directory compatibility check

- - {isCompatible &&

Your existing OpenSearch data can be migrated to Data Node.

} - {!isError && !isCompatible && ( - <> -

Your existing OpenSearch data cannot be migrated to Data Node.

-
- Error: {errors} {errors.map((error) =>
{error}
)} - - )} - {isError && ( - <> -

There was an error checking the compatibility

-

{requestError.message}

- - )} -
+ {isCompatible && !warnings.length && ( + +

Your existing OpenSearch data can be migrated to Data Node.

+
+ )} + {(!isCompatible || isError) && ( + + {!isError && !isCompatible && ( + <> +

Your existing OpenSearch data cannot be migrated to Data Node.

+
+ {errors.map((error) =>
{error}
)} + + )} + {isError && ( + <> +

There was an error checking the compatibility

+

{requestError.message}

+ + )} +
+ )} + {warnings.length > 0 && ( + + {warnings.map((warning) =>
{warning}
)} +
+ )}
{!isCompatible && (

Your OpenSearch cluster cannot be migrated to this Data Node version because it's not compatible.

)} {isCompatible && data && Object.keys(data).map((hostname) => (