diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/AbstractS3CompatibleConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/AbstractS3CompatibleConnectivityTester.java index 23a5d407dcd644..df9de5cb77cca4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/AbstractS3CompatibleConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/AbstractS3CompatibleConnectivityTester.java @@ -66,4 +66,10 @@ public void testFeConnection() throws Exception { client.headBucket(b -> b.bucket(s3Uri.getBucket())); } } + + @Override + public String getErrorHint() { + return "Please check S3 credentials (access_key and secret_key or IAM role), " + + "region, and bucket (warehouse location) access permissions"; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/CatalogConnectivityTestCoordinator.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/CatalogConnectivityTestCoordinator.java index 35b3ba744c3304..cf8c308849a936 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/CatalogConnectivityTestCoordinator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/CatalogConnectivityTestCoordinator.java @@ -18,6 +18,7 @@ package org.apache.doris.datasource.connectivity; import org.apache.doris.common.DdlException; +import org.apache.doris.common.util.Util; import org.apache.doris.datasource.property.metastore.HiveGlueMetaStoreProperties; import org.apache.doris.datasource.property.metastore.HiveHMSProperties; import org.apache.doris.datasource.property.metastore.IcebergGlueMetaStoreProperties; @@ -94,8 +95,10 @@ private void testMetadataService() throws DdlException { try { metaTester.testConnection(); } catch (Exception e) { - throw new DdlException(metaTester.getTestType() + " connectivity test failed: " - + e.getMessage()); + String hint = metaTester.getErrorHint(); + String errorMsg = metaTester.getTestType() + " connectivity test failed: " + hint + + " Root cause: " + Util.getRootCauseMessage(e); + throw new DdlException(errorMsg); } // Store warehouse location for later use @@ -142,15 +145,20 @@ private void testObjectStorageForWarehouse(StorageProperties testObjectStoragePr try { tester.testFeConnection(); } catch (Exception e) { - throw new DdlException(tester.getTestType() + " connectivity test failed: " + e.getMessage()); + String hint = tester.getErrorHint(); + String errorMsg = tester.getTestType() + " connectivity test failed: " + hint + + " Root cause: " + Util.getRootCauseMessage(e); + throw new DdlException(errorMsg); } // Test BE connection try { tester.testBeConnection(); } catch (Exception e) { - throw new DdlException(tester.getTestType() - + " connectivity test failed (compute node): " + e.getMessage()); + String hint = tester.getErrorHint(); + String errorMsg = tester.getTestType() + " connectivity test failed (compute node): " + hint + + " Root cause: " + Util.getRootCauseMessage(e); + throw new DdlException(errorMsg); } } @@ -240,14 +248,20 @@ private void testExplicitlyConfiguredHdfs() throws DdlException { try { tester.testFeConnection(); } catch (Exception e) { - throw new DdlException("HDFS connectivity test failed: " + e.getMessage()); + String hint = tester.getErrorHint(); + String errorMsg = "HDFS connectivity test failed: " + hint + + " Root cause: " + Util.getRootCauseMessage(e); + throw new DdlException(errorMsg); } // Test BE connection try { tester.testBeConnection(); } catch (Exception e) { - throw new DdlException("HDFS connectivity test failed (compute node): " + e.getMessage()); + String hint = tester.getErrorHint(); + String errorMsg = "HDFS connectivity test failed (compute node): " + hint + + " Root cause: " + Util.getRootCauseMessage(e); + throw new DdlException(errorMsg); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HdfsCompatibleConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HdfsCompatibleConnectivityTester.java index 481017463d8f98..cd1be0fa9efb08 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HdfsCompatibleConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HdfsCompatibleConnectivityTester.java @@ -37,6 +37,12 @@ public String getTestType() { return "HDFS"; } + @Override + public String getErrorHint() { + return "Please check HDFS namenode connectivity (fs.defaultFS), user permissions, and " + + "Kerberos configuration if applicable"; + } + @Override public void testFeConnection() throws Exception { // TODO: Implement HDFS connectivity test in the future if needed diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveGlueMetaStoreConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveGlueMetaStoreConnectivityTester.java index 87edad2c8bead8..f6b4002fa16a86 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveGlueMetaStoreConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveGlueMetaStoreConnectivityTester.java @@ -34,6 +34,12 @@ public String getTestType() { return "Hive Glue"; } + @Override + public String getErrorHint() { + return "Please check AWS Glue credentials (access_key and secret_key or IAM role), region, " + + "and endpoint"; + } + @Override public void testConnection() throws Exception { glueTester.testConnection(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveHMSConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveHMSConnectivityTester.java index 367a2428bdaf73..855d18b2f0a3aa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveHMSConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/HiveHMSConnectivityTester.java @@ -33,6 +33,11 @@ public String getTestType() { return "Hive HMS"; } + @Override + public String getErrorHint() { + return "Please check Hive Metastore Server connectivity (hive metastore uris)"; + } + @Override public void testConnection() throws Exception { hmsTester.testConnection(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergGlueMetaStoreConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergGlueMetaStoreConnectivityTester.java index 3a543d194a706b..978fffceb732b3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergGlueMetaStoreConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergGlueMetaStoreConnectivityTester.java @@ -20,7 +20,12 @@ import org.apache.doris.datasource.property.metastore.AWSGlueMetaStoreBaseProperties; import org.apache.doris.datasource.property.metastore.AbstractIcebergProperties; +import org.apache.commons.lang3.StringUtils; + +import java.util.regex.Pattern; + public class IcebergGlueMetaStoreConnectivityTester extends AbstractIcebergConnectivityTester { + private static final Pattern S3_LOCATION_PATTERN = Pattern.compile("^(s3|s3a)://.+"); private final AWSGlueMetaStoreBaseConnectivityTester glueTester; public IcebergGlueMetaStoreConnectivityTester(AbstractIcebergProperties properties, @@ -34,8 +39,36 @@ public String getTestType() { return "Iceberg Glue"; } + @Override + public String getErrorHint() { + return "Please check AWS Glue credentials (access_key and secret_key or IAM role), " + + "region, warehouse location, and endpoint"; + } + @Override public void testConnection() throws Exception { glueTester.testConnection(); } + + @Override + public String getTestLocation() { + String warehouse = properties.getWarehouse(); + if (StringUtils.isBlank(warehouse)) { + return null; + } + + String location = validateS3Location(warehouse); + if (location == null) { + throw new IllegalArgumentException( + "Iceberg Glue warehouse location must be in S3 format (s3:// or s3a://), but got: " + warehouse); + } + return location; + } + + private String validateS3Location(String location) { + if (StringUtils.isNotBlank(location) && S3_LOCATION_PATTERN.matcher(location).matches()) { + return location; + } + return null; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergHMSConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergHMSConnectivityTester.java index 04ff5ea385c83e..99fc6a42740df8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergHMSConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergHMSConnectivityTester.java @@ -33,6 +33,11 @@ public String getTestType() { return "Iceberg HMS"; } + @Override + public String getErrorHint() { + return "Please check Hive Metastore Server connectivity (hive metastore uris)"; + } + @Override public void testConnection() throws Exception { hmsTester.testConnection(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergRestConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergRestConnectivityTester.java index a9659d60d2d345..ca00fba1501d2c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergRestConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergRestConnectivityTester.java @@ -43,6 +43,12 @@ public String getTestType() { return "Iceberg REST"; } + @Override + public String getErrorHint() { + return "Please check Iceberg REST Catalog URI, authentication credentials (OAuth2 or SigV4), " + + "warehouse location, and endpoint connectivity"; + } + @Override public void testConnection() throws Exception { Map restProps = ((IcebergRestProperties) properties).getIcebergRestCatalogProperties(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergS3TablesMetaStoreConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergS3TablesMetaStoreConnectivityTester.java index c4444839771561..ad587aaf77ab2e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergS3TablesMetaStoreConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/IcebergS3TablesMetaStoreConnectivityTester.java @@ -25,6 +25,12 @@ protected IcebergS3TablesMetaStoreConnectivityTester( super(properties); } + @Override + public String getErrorHint() { + return "Please check S3 credentials (access_key and secret_key or IAM role), endpoint, region, " + + "and warehouse location"; + } + @Override public void testConnection() throws Exception { // TODO: Implement Iceberg S3 Tables connectivity test in the future if needed diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MetaConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MetaConnectivityTester.java index 2f2a9a34140dc9..326f6c5b20f8f0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MetaConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MetaConnectivityTester.java @@ -34,4 +34,12 @@ default String getTestLocation() { default String getTestType() { return "Meta"; } + + /** + * Returns error hint for this connectivity test. + * Subclasses can override to provide specific hints for troubleshooting. + */ + default String getErrorHint() { + return ""; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MinioConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MinioConnectivityTester.java index 6c9ada8c490d4a..32ce99714e052f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MinioConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/MinioConnectivityTester.java @@ -29,4 +29,10 @@ public MinioConnectivityTester(MinioProperties properties, String testLocation) public String getTestType() { return "Minio"; } + + @Override + public String getErrorHint() { + return "Please check Minio credentials (access_key and secret_key), " + + "endpoint, and bucket (warehouse location) access permissions"; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/StorageConnectivityTester.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/StorageConnectivityTester.java index 7f23c674f71e3c..a3248691fc6e1e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/StorageConnectivityTester.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/connectivity/StorageConnectivityTester.java @@ -53,6 +53,14 @@ default String getTestType() { return "Storage"; } + /** + * Returns error hint for this connectivity test. + * Subclasses can override to provide specific hints for troubleshooting. + */ + default String getErrorHint() { + return ""; + } + default void testBeConnection() throws Exception { List aliveBeIds = Env.getCurrentSystemInfo().getAllBackendIds(true); if (aliveBeIds.isEmpty()) {