This is an automated email from the ASF dual-hosted git repository.

rong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 51ee13be2da AINode: Introduce IT framework (#13387)
51ee13be2da is described below

commit 51ee13be2da7fefbfff7afb1289fe39ecfa9ce6c
Author: YangCaiyin <[email protected]>
AuthorDate: Wed Sep 4 14:33:01 2024 +0800

    AINode: Introduce IT framework (#13387)
---
 .github/workflows/cluster-it-1c1d1a.yml            |  62 +++++++
 integration-test/pom.xml                           |  14 ++
 integration-test/src/assembly/mpp-test.xml         |  19 +++
 .../java/org/apache/iotdb/it/env/EnvFactory.java   |   4 +
 .../main/java/org/apache/iotdb/it/env/EnvType.java |   1 +
 .../iotdb/it/env/cluster/ClusterConstant.java      |   3 +
 .../env/{EnvType.java => cluster/env/AIEnv.java}   |  26 +--
 .../iotdb/it/env/cluster/env/AbstractEnv.java      |  53 +++++-
 .../iotdb/it/env/cluster/node/AINodeWrapper.java   | 179 +++++++++++++++++++++
 .../it/env/cluster/node/AbstractNodeWrapper.java   |  12 +-
 .../category/AIClusterIT.java}                     |  16 +-
 .../java/org/apache/iotdb/ainode/it/AIEnvIT.java   |  80 +++++++++
 iotdb-core/ainode/pyproject.toml                   |   2 +-
 .../ainode/resources/conf/iotdb-ainode.properties  |   8 +-
 pom.xml                                            |   7 +-
 15 files changed, 443 insertions(+), 43 deletions(-)

diff --git a/.github/workflows/cluster-it-1c1d1a.yml 
b/.github/workflows/cluster-it-1c1d1a.yml
new file mode 100644
index 00000000000..a92d9d23811
--- /dev/null
+++ b/.github/workflows/cluster-it-1c1d1a.yml
@@ -0,0 +1,62 @@
+name: Cluster IT - 1C1D1A
+
+on:
+  push:
+    branches:
+      - master
+      - 'rel/1.*'
+      - 'rc/1.*'
+    paths-ignore:
+      - 'docs/**'
+      - 'site/**'
+  pull_request:
+    branches:
+      - master
+      - 'rel/1.*'
+      - 'rc/1.*'
+    paths-ignore:
+      - 'docs/**'
+      - 'site/**'
+  # allow manually run the action:
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+env:
+  MAVEN_OPTS: -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false 
-Dmaven.wagon.http.retryHandler.class=standard 
-Dmaven.wagon.http.retryHandler.count=3
+  MAVEN_ARGS: --batch-mode --no-transfer-progress
+  DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
+
+jobs:
+  AINode:
+    strategy:
+      fail-fast: false
+      max-parallel: 15
+      matrix:
+        os: [ ubuntu-latest ]
+    runs-on: ${{ matrix.os }}
+
+    steps:
+      - uses: actions/checkout@v4
+      - name: Build AINode
+        shell: bash
+        run: mvn clean package -DskipTests -P with-ainode
+      - name: IT Test
+        shell: bash
+        run: |
+          mvn clean verify \
+          -P with-integration-tests \
+          -DskipUTs \
+          -DintegrationTest.forkCount=2 \
+          -pl integration-test \
+          -am \
+          -PAIClusterIT
+      - name: Upload Artifact
+        if: failure()
+        uses: actions/upload-artifact@v4
+        with:
+          name: cluster-log-ainode-${{ matrix.os }}
+          path: integration-test/target/ainode-logs
+          retention-days: 30
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index 5fe4a48628f..a34f517dc71 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -534,6 +534,20 @@
                 <integrationTest.testEnv>Cluster1</integrationTest.testEnv>
             </properties>
         </profile>
+        <profile>
+            <id>AIClusterIT</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <properties>
+                <integrationTest.excludedGroups/>
+                
<integrationTest.includedGroups>org.apache.iotdb.itbase.category.AIClusterIT</integrationTest.includedGroups>
+                
<integrationTest.launchNodeInSameJVM>false</integrationTest.launchNodeInSameJVM>
+                
<integrationTest.randomSelectWriteNode>false</integrationTest.randomSelectWriteNode>
+                
<integrationTest.readAndVerifyWithMultiNode>false</integrationTest.readAndVerifyWithMultiNode>
+                <integrationTest.testEnv>AI</integrationTest.testEnv>
+            </properties>
+        </profile>
         <profile>
             <id>DailyIT</id>
             <activation>
diff --git a/integration-test/src/assembly/mpp-test.xml 
b/integration-test/src/assembly/mpp-test.xml
index 3dc443c8d03..9a4a8727ea2 100644
--- a/integration-test/src/assembly/mpp-test.xml
+++ b/integration-test/src/assembly/mpp-test.xml
@@ -42,6 +42,10 @@
             <outputDirectory>conf</outputDirectory>
             
<directory>${project.basedir}/../iotdb-core/metrics/interface/src/main/assembly/resources/conf</directory>
         </fileSet>
+        <fileSet>
+            <outputDirectory>conf</outputDirectory>
+            
<directory>${project.basedir}/../iotdb-core/ainode/resources/conf</directory>
+        </fileSet>
         <fileSet>
             <outputDirectory>sbin</outputDirectory>
             
<directory>${project.basedir}/../iotdb-core/datanode/src/assembly/resources/sbin</directory>
@@ -52,6 +56,16 @@
             
<directory>${project.basedir}/../iotdb-core/confignode/src/assembly/resources/sbin</directory>
             <fileMode>0755</fileMode>
         </fileSet>
+        <fileSet>
+            <outputDirectory>sbin</outputDirectory>
+            
<directory>${project.basedir}/../iotdb-core/ainode/resources/sbin</directory>
+            <fileMode>0755</fileMode>
+        </fileSet>
+        <fileSet>
+            <outputDirectory>venv</outputDirectory>
+            <directory>${project.basedir}/../iotdb-core/ainode/venv</directory>
+            <fileMode>0755</fileMode>
+        </fileSet>
         <fileSet>
             <outputDirectory>tools</outputDirectory>
             
<directory>${project.basedir}/../iotdb-core/datanode/src/assembly/resources/tools</directory>
@@ -67,6 +81,11 @@
             
<directory>${project.basedir}/../iotdb-client/cli/src/assembly/resources/tools</directory>
             <fileMode>0755</fileMode>
         </fileSet>
+        <fileSet>
+            <outputDirectory>lib</outputDirectory>
+            
<directory>${project.basedir}/../iotdb-core/ainode/dist/</directory>
+            <fileMode>0755</fileMode>
+        </fileSet>
     </fileSets>
     <files>
         <file>
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvFactory.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/EnvFactory.java
index 054127da6f9..ce8046708a8 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvFactory.java
+++ b/integration-test/src/main/java/org/apache/iotdb/it/env/EnvFactory.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.it.env;
 
+import org.apache.iotdb.it.env.cluster.env.AIEnv;
 import org.apache.iotdb.it.env.cluster.env.Cluster1Env;
 import org.apache.iotdb.it.env.cluster.env.SimpleEnv;
 import org.apache.iotdb.it.env.remote.env.RemoteServerEnv;
@@ -54,6 +55,9 @@ public class EnvFactory {
           case Remote:
             env = new RemoteServerEnv();
             break;
+          case AI:
+            env = new AIEnv();
+            break;
           case MultiCluster:
             logger.warn(
                 "EnvFactory only supports EnvType Simple, Cluster1 and Remote, 
please use MultiEnvFactory instead.");
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
index 974af1fc22c..7c2ee415cf1 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
+++ b/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
@@ -24,6 +24,7 @@ public enum EnvType {
   Simple,
   Cluster1,
   MultiCluster,
+  AI,
   TABLE_SIMPLE,
   TABLE_CLUSTER1;
 
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/ClusterConstant.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/ClusterConstant.java
index e685dd74ed2..b3802f3ea8d 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/ClusterConstant.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/ClusterConstant.java
@@ -182,9 +182,12 @@ public class ClusterConstant {
   // Paths
   public static final String USER_DIR = "user.dir";
   public static final String TARGET = "target";
+  public static final String PYTHON_PATH = "venv/bin/python3";
 
   public static final String DATA_NODE_NAME = "DataNode";
 
+  public static final String AI_NODE_NAME = "AINode";
+
   public static final String LOCK_FILE_PATH =
       System.getProperty(USER_DIR) + File.separator + TARGET + File.separator 
+ "lock-";
   public static final String TEMPLATE_NODE_PATH =
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AIEnv.java
similarity index 59%
copy from integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
copy to 
integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AIEnv.java
index 974af1fc22c..a037e121509 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AIEnv.java
@@ -17,18 +17,22 @@
  * under the License.
  */
 
-package org.apache.iotdb.it.env;
+package org.apache.iotdb.it.env.cluster.env;
 
-public enum EnvType {
-  Remote,
-  Simple,
-  Cluster1,
-  MultiCluster,
-  TABLE_SIMPLE,
-  TABLE_CLUSTER1;
+public class AIEnv extends AbstractEnv {
+  @Override
+  public void initClusterEnvironment() {
+    initClusterEnvironment(1, 1);
+  }
+
+  @Override
+  public void initClusterEnvironment(int configNodesNum, int dataNodesNum) {
+    super.initEnvironment(configNodesNum, dataNodesNum, 10000, true);
+  }
 
-  public static EnvType getSystemEnvType() {
-    String envValue = System.getProperty("TestEnv", Simple.name());
-    return EnvType.valueOf(envValue);
+  @Override
+  public void initClusterEnvironment(
+      int configNodesNum, int dataNodesNum, int testWorkingRetryCount) {
+    super.initEnvironment(configNodesNum, dataNodesNum, testWorkingRetryCount, 
true);
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index 33b49f94032..482e869cf1c 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -41,6 +41,7 @@ import org.apache.iotdb.isession.pool.ISessionPool;
 import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.env.cluster.EnvUtils;
 import org.apache.iotdb.it.env.cluster.config.*;
+import org.apache.iotdb.it.env.cluster.node.AINodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.ConfigNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
@@ -81,6 +82,7 @@ public abstract class AbstractEnv implements BaseEnv {
   private final Random rand = new Random();
   protected List<ConfigNodeWrapper> configNodeWrapperList = 
Collections.emptyList();
   protected List<DataNodeWrapper> dataNodeWrapperList = 
Collections.emptyList();
+  protected List<AINodeWrapper> aiNodeWrapperList = Collections.emptyList();
   protected String testMethodName = null;
   protected int index = 0;
   protected long startTime;
@@ -144,7 +146,12 @@ public abstract class AbstractEnv implements BaseEnv {
     initEnvironment(configNodesNum, dataNodesNum, retryCount);
   }
 
-  protected void initEnvironment(int configNodesNum, int dataNodesNum, int 
retryCount) {
+  protected void initEnvironment(int configNodesNum, int dataNodesNum, int 
testWorkingRetryCount) {
+    initEnvironment(configNodesNum, dataNodesNum, testWorkingRetryCount, 
false);
+  }
+
+  protected void initEnvironment(
+      int configNodesNum, int dataNodesNum, int retryCount, boolean addAINode) 
{
     this.retryCount = retryCount;
     this.configNodeWrapperList = new ArrayList<>();
     this.dataNodeWrapperList = new ArrayList<>();
@@ -256,9 +263,45 @@ public abstract class AbstractEnv implements BaseEnv {
       throw new AssertionError();
     }
 
+    if (addAINode) {
+      this.aiNodeWrapperList = new ArrayList<>();
+      startAINode(seedConfigNode, testClassName);
+    }
+
     checkClusterStatusWithoutUnknown();
   }
 
+  private void startAINode(String seedConfigNode, String testClassName) {
+    String aiNodeEndPoint;
+    AINodeWrapper aiNodeWrapper =
+        new AINodeWrapper(
+            seedConfigNode,
+            testClassName,
+            testMethodName,
+            index,
+            EnvUtils.searchAvailablePorts(),
+            startTime);
+    aiNodeWrapperList.add(aiNodeWrapper);
+    aiNodeEndPoint = aiNodeWrapper.getIpAndPortString();
+    aiNodeWrapper.createNodeDir();
+    aiNodeWrapper.createLogDir();
+    RequestDelegate<Void> AINodesDelegate =
+        new ParallelRequestDelegate<>(
+            Collections.singletonList(aiNodeEndPoint), NODE_START_TIMEOUT);
+
+    AINodesDelegate.addRequest(
+        () -> {
+          aiNodeWrapper.start();
+          return null;
+        });
+
+    try {
+      AINodesDelegate.requestAll();
+    } catch (SQLException e) {
+      logger.error("Start aiNodes failed", e);
+    }
+  }
+
   public String getTestClassName() {
     StackTraceElement[] stack = Thread.currentThread().getStackTrace();
     for (StackTraceElement stackTraceElement : stack) {
@@ -319,7 +362,9 @@ public abstract class AbstractEnv implements BaseEnv {
 
         // Check the number of nodes
         if (showClusterResp.getNodeStatus().size()
-            != configNodeWrapperList.size() + dataNodeWrapperList.size()) {
+            != configNodeWrapperList.size()
+                + dataNodeWrapperList.size()
+                + aiNodeWrapperList.size()) {
           flag = false;
         }
 
@@ -356,7 +401,9 @@ public abstract class AbstractEnv implements BaseEnv {
   @Override
   public void cleanClusterEnvironment() {
     List<AbstractNodeWrapper> allNodeWrappers =
-        Stream.concat(this.dataNodeWrapperList.stream(), 
this.configNodeWrapperList.stream())
+        Stream.concat(
+                dataNodeWrapperList.stream(),
+                Stream.concat(configNodeWrapperList.stream(), 
aiNodeWrapperList.stream()))
             .collect(Collectors.toList());
     allNodeWrappers.stream()
         .findAny()
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AINodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AINodeWrapper.java
new file mode 100644
index 00000000000..c503dfc00e7
--- /dev/null
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AINodeWrapper.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.it.env.cluster.node;
+
+import org.apache.iotdb.it.env.cluster.config.MppJVMConfig;
+import org.apache.iotdb.it.framework.IoTDBTestLogger;
+
+import org.slf4j.Logger;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.iotdb.it.env.cluster.ClusterConstant.AI_NODE_NAME;
+import static org.apache.iotdb.it.env.cluster.ClusterConstant.PYTHON_PATH;
+import static org.apache.iotdb.it.env.cluster.ClusterConstant.TARGET;
+import static org.apache.iotdb.it.env.cluster.ClusterConstant.USER_DIR;
+import static org.apache.iotdb.it.env.cluster.EnvUtils.getTimeForLogDirectory;
+
+public class AINodeWrapper extends AbstractNodeWrapper {
+
+  private static final Logger logger = IoTDBTestLogger.logger;
+  private final long startTime;
+  private final String seedConfigNode;
+
+  private static final String SCRIPT_FILE = "start-ainode.sh";
+
+  private static final String SHELL_COMMAND = "bash";
+
+  private static final String PROPERTIES_FILE = "iotdb-ainode.properties";
+  public static final String CONFIG_PATH = "conf";
+  public static final String SCRIPT_PATH = "sbin";
+
+  private void replaceAttribute(String[] keys, String[] values, String 
filePath) {
+    try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, 
true))) {
+      for (int i = 0; i < keys.length; i++) {
+        String line = keys[i] + "=" + values[i];
+        writer.newLine();
+        writer.write(line);
+      }
+    } catch (IOException e) {
+      logger.error(
+          "Failed to set attribute for AINode in file: {} because {}", 
filePath, e.getMessage());
+    }
+  }
+
+  public AINodeWrapper(
+      String seedConfigNode,
+      String testClassName,
+      String testMethodName,
+      int clusterIndex,
+      int[] port,
+      long startTime) {
+    super(testClassName, testMethodName, port, clusterIndex, false, startTime);
+    this.seedConfigNode = seedConfigNode;
+    this.startTime = startTime;
+  }
+
+  @Override
+  public String getLogDirPath() {
+    return System.getProperty(USER_DIR)
+        + File.separator
+        + TARGET
+        + File.separator
+        + "ainode-logs"
+        + File.separator
+        + getTestLogDirName()
+        + File.separator
+        + getTimeForLogDirectory(startTime);
+  }
+
+  @Override
+  public void start() {
+    try {
+      File stdoutFile = new File(getLogPath());
+      String filePrefix =
+          System.getProperty(USER_DIR)
+              + File.separator
+              + TARGET
+              + File.separator
+              + AI_NODE_NAME
+              + getPort();
+      String propertiesFile =
+          filePrefix + File.separator + CONFIG_PATH + File.separator + 
PROPERTIES_FILE;
+
+      // set attribute
+      replaceAttribute(
+          new String[] {"ain_seed_config_node", "ain_inference_rpc_port"},
+          new String[] {this.seedConfigNode, Integer.toString(getPort())},
+          propertiesFile);
+
+      // start AINode
+      List<String> startCommand = new ArrayList<>();
+      startCommand.add(SHELL_COMMAND);
+      startCommand.add(filePrefix + File.separator + SCRIPT_PATH + 
File.separator + SCRIPT_FILE);
+      startCommand.add("-i");
+      startCommand.add(filePrefix + File.separator + PYTHON_PATH);
+      startCommand.add("-r");
+
+      ProcessBuilder processBuilder =
+          new ProcessBuilder(startCommand)
+              .redirectOutput(ProcessBuilder.Redirect.appendTo(stdoutFile))
+              .redirectError(ProcessBuilder.Redirect.appendTo(stdoutFile));
+      this.instance = processBuilder.start();
+      logger.info("In test {} {} started.", getTestLogDirName(), getId());
+    } catch (Exception e) {
+      throw new AssertionError("Start AI Node failed. " + e + Paths.get(""));
+    }
+  }
+
+  @Override
+  public int getMetricPort() {
+    // no metric currently
+    return -1;
+  }
+
+  @Override
+  public String getId() {
+    return AI_NODE_NAME + getPort();
+  }
+
+  /* Abstract methods, which must be implemented in ConfigNode and DataNode. */
+  public void reloadMutableFields() {}
+  ;
+
+  public void renameFile() {}
+  ;
+
+  public String getSystemConfigPath() {
+    return "";
+  }
+  ;
+
+  /** Return the node config file path specified through system variable */
+  public String getDefaultNodeConfigPath() {
+    return "";
+  }
+  ;
+
+  /** Return the common config file path specified through system variable */
+  public String getDefaultCommonConfigPath() {
+    return "";
+  }
+  ;
+
+  public void addStartCmdParams(List<String> params) {}
+  ;
+
+  public String getSystemPropertiesPath() {
+    return "";
+  }
+  ;
+
+  public MppJVMConfig initVMConfig() {
+    return null;
+  }
+  ;
+}
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
index 942b6a9e012..bf28c407f72 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
@@ -125,11 +125,11 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
   protected final MppJVMConfig jvmConfig;
   protected final int clusterIndex;
   protected final boolean isMultiCluster;
-  private Process instance;
+  protected Process instance;
   private final String nodeAddress;
   private int nodePort;
-  private int metricPort;
-  private long startTime;
+  private final int metricPort;
+  private final long startTime;
   private List<String> killPoints = new ArrayList<>();
 
   /**
@@ -523,7 +523,7 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
   }
 
   @Override
-  public final int getMetricPort() {
+  public int getMetricPort() {
     return this.metricPort;
   }
 
@@ -540,7 +540,7 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
     return getNodePath() + File.separator + dirName + File.separator + 
fileName;
   }
 
-  private String getLogPath() {
+  protected String getLogPath() {
     return getLogDirPath() + File.separator + getId() + ".log";
   }
 
@@ -645,7 +645,7 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
     output.print(sb);
   }
 
-  private String getTestLogDirName() {
+  protected String getTestLogDirName() {
     if (testMethodName == null) {
       return testClassName;
     }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java 
b/integration-test/src/main/java/org/apache/iotdb/itbase/category/AIClusterIT.java
similarity index 73%
copy from integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
copy to 
integration-test/src/main/java/org/apache/iotdb/itbase/category/AIClusterIT.java
index 974af1fc22c..ab3c458cd79 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/EnvType.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/category/AIClusterIT.java
@@ -17,18 +17,6 @@
  * under the License.
  */
 
-package org.apache.iotdb.it.env;
+package org.apache.iotdb.itbase.category;
 
-public enum EnvType {
-  Remote,
-  Simple,
-  Cluster1,
-  MultiCluster,
-  TABLE_SIMPLE,
-  TABLE_CLUSTER1;
-
-  public static EnvType getSystemEnvType() {
-    String envValue = System.getProperty("TestEnv", Simple.name());
-    return EnvType.valueOf(envValue);
-  }
-}
+public interface AIClusterIT {}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AIEnvIT.java 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AIEnvIT.java
new file mode 100644
index 00000000000..3f1aad95a32
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AIEnvIT.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.ainode.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.AIClusterIT;
+
+import org.junit.*;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({AIClusterIT.class})
+public class AIEnvIT {
+  @Before
+  public void setUp() throws Exception {
+    // Init 1C1D1M cluster environment
+    EnvFactory.getEnv().initClusterEnvironment(1, 1);
+  }
+
+  @After
+  public void tearDown() {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  private static void checkHeader(ResultSetMetaData resultSetMetaData, String 
title)
+      throws SQLException {
+    String[] headers = title.split(",");
+    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+      assertEquals(headers[i - 1], resultSetMetaData.getColumnName(i));
+    }
+  }
+
+  @Test
+  public void aiNodeConnectionTest() {
+    String sql = "SHOW AINODES";
+    String title = "NodeID,Status,RpcAddress,RpcPort";
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+
+      try (ResultSet resultSet = statement.executeQuery(sql)) {
+        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+        checkHeader(resultSetMetaData, title);
+        int count = 0;
+        while (resultSet.next()) {
+          assertEquals("2", resultSet.getString(1));
+          assertEquals("Running", resultSet.getString(2));
+          count++;
+        }
+        assertEquals(1, count);
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+}
diff --git a/iotdb-core/ainode/pyproject.toml b/iotdb-core/ainode/pyproject.toml
index 0d1103ea716..6211d230136 100644
--- a/iotdb-core/ainode/pyproject.toml
+++ b/iotdb-core/ainode/pyproject.toml
@@ -50,7 +50,7 @@ python = ">=3.8, <3.13"
 
 numpy = "^1.21.4"
 pandas = "^1.3.5"
-torch = "2.1.0"
+torch = "2.2.0"
 pylru = "^1.2.1"
 
 thrift = "^0.13.0"
diff --git a/iotdb-core/ainode/resources/conf/iotdb-ainode.properties 
b/iotdb-core/ainode/resources/conf/iotdb-ainode.properties
index 52b3dbb1bb0..2b208e72125 100644
--- a/iotdb-core/ainode/resources/conf/iotdb-ainode.properties
+++ b/iotdb-core/ainode/resources/conf/iotdb-ainode.properties
@@ -19,22 +19,22 @@
 
 # Used for indicate cluster name and distinguish different cluster.
 # Datatype: string
-cluster_name=defaultCluster
+# cluster_name=defaultCluster
 
 # ConfigNode address registered at AINode startup
 # Allow modifications only before starting the service for the first time
 # Datatype: String
-ain_seed_config_node=127.0.0.1:10710
+# ain_seed_config_node=127.0.0.1:10710
 
 # Used for connection of DataNode/ConfigNode clients
 # Could set 127.0.0.1(for local test) or ipv4 address
 # Datatype: String
-ain_inference_rpc_address=127.0.0.1
+# ain_inference_rpc_address=127.0.0.1
 
 # Used for connection of DataNode/ConfigNode clients
 # Bind with MN_RPC_ADDRESS
 # Datatype: String
-ain_inference_rpc_port=10810
+# ain_inference_rpc_port=10810
 
 # The AINode metadata storage path.
 # The starting directory of the relative path is related to the operating 
system.
diff --git a/pom.xml b/pom.xml
index c537864287d..eae203cc7e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -779,6 +779,7 @@
                             <exclude>**/.gitignore</exclude>
                             <exclude>**/.gitmodules</exclude>
                             <exclude>**/.git-blame-ignore-revs</exclude>
+                            <exclude>**/git.properties</exclude>
                             <!-- Maven related files -->
                             <exclude>**/target/**</exclude>
                             <!-- Eclipse related files -->
@@ -821,11 +822,9 @@
                             <exclude>client-go/rpc/*</exclude>
                             <!-- python -->
                             <exclude>.pytest_cache/**</exclude>
-                            <exclude>venv/**</exclude>
+                            <exclude>**/venv/**</exclude>
                             <exclude>apache_iotdb.egg-info/**</exclude>
-                            <exclude>**/iotdb/thrift/__init__.py</exclude>
-                            <exclude>**/iotdb/thrift/rpc/__init__.py</exclude>
-                            
<exclude>**/iotdb/thrift/common/__init__.py</exclude>
+                            <exclude>**/thrift/**/__init__.py</exclude>
                             <!-- Java SPI uses files in 
resources/META-INF/services-->
                             
<exclude>**/resources/META-INF/services/**</exclude>
                             <!-- site-->

Reply via email to