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

liuhaopeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git


The following commit(s) were added to refs/heads/main by this push:
     new df23edbb BIGTOP-4425: Skip agent installation if user already 
installed (#217)
df23edbb is described below

commit df23edbb112879c23d817d6c38499d99131ccd5e
Author: Zhiguo Wu <[email protected]>
AuthorDate: Tue May 20 10:59:48 2025 +0800

    BIGTOP-4425: Skip agent installation if user already installed (#217)
---
 .../src/main/resources/application.yml             |   2 +-
 .../manager/common/utils/ProjectPathUtils.java     |   4 +
 .../manager/dao/repository/ComponentDao.java       |   2 +
 .../bigtop/manager/dao/repository/ToolDao.java     |   7 +-
 .../resources/mapper/mysql/ComponentMapper.xml     |  19 ++++
 .../src/main/resources/mapper/mysql/ToolMapper.xml |  41 +++++++
 .../mapper/postgresql/ComponentMapper.xml          |  19 ++++
 .../resources/mapper/postgresql/ToolMapper.xml     |  41 +++++++
 .../src/main/assembly/assembly-server.xml          |   6 ++
 .../command/job/component/ComponentAddJob.java     |   7 +-
 .../server/service/impl/HostServiceImpl.java       |  87 +++++----------
 .../src/main/resources/ddl/MySQL-DDL-CREATE.sql    |   1 +
 .../main/resources/ddl/PostgreSQL-DDL-CREATE.sql   |   1 +
 .../src/main/resources/scripts/setup-agent.sh      | 118 +++++++++++++++++++++
 dev-support/docker/containers/build.sh             |   6 +-
 15 files changed, 291 insertions(+), 70 deletions(-)

diff --git a/bigtop-manager-agent/src/main/resources/application.yml 
b/bigtop-manager-agent/src/main/resources/application.yml
index ee8a251e..5d5ce3ed 100644
--- a/bigtop-manager-agent/src/main/resources/application.yml
+++ b/bigtop-manager-agent/src/main/resources/application.yml
@@ -30,7 +30,7 @@ server:
 
 grpc:
   server:
-    port: 8835
+    port: ${GRPC_PORT:8835}
 
 logging:
   level:
diff --git 
a/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/utils/ProjectPathUtils.java
 
b/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/utils/ProjectPathUtils.java
index 6bf3bf3f..f8f63c08 100644
--- 
a/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/utils/ProjectPathUtils.java
+++ 
b/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/utils/ProjectPathUtils.java
@@ -43,6 +43,10 @@ public class ProjectPathUtils {
         return getProjectResourcesDir() + File.separator + "stacks";
     }
 
+    public static String getServerScriptPath() {
+        return getProjectResourcesDir() + File.separator + "scripts";
+    }
+
     public static String getAgentCachePath() {
         return getProjectStoreDir() + File.separator + "agent-caches";
     }
diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ComponentDao.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ComponentDao.java
index 5dd46b90..f22bcad0 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ComponentDao.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ComponentDao.java
@@ -32,5 +32,7 @@ public interface ComponentDao extends BaseDao<ComponentPO> {
 
     List<ComponentPO> findByQuery(@Param("query") ComponentQuery query);
 
+    ComponentPO findByNameAndHostname(@Param("name") String name, 
@Param("hostname") String hostname);
+
     ComponentPO findDetailsById(@Param("id") Long id);
 }
diff --git 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ToolDao.java
 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ToolDao.java
index 3306e41c..b09f60ba 100644
--- 
a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ToolDao.java
+++ 
b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/ToolDao.java
@@ -21,4 +21,9 @@ package org.apache.bigtop.manager.dao.repository;
 
 import org.apache.bigtop.manager.dao.po.ToolPO;
 
-public interface ToolDao extends BaseDao<ToolPO> {}
+import org.apache.ibatis.annotations.Param;
+
+public interface ToolDao extends BaseDao<ToolPO> {
+
+    ToolPO findByName(@Param("name") String name);
+}
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/mysql/ComponentMapper.xml 
b/bigtop-manager-dao/src/main/resources/mapper/mysql/ComponentMapper.xml
index 4f87b36e..2d5d44f4 100644
--- a/bigtop-manager-dao/src/main/resources/mapper/mysql/ComponentMapper.xml
+++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/ComponentMapper.xml
@@ -80,6 +80,25 @@
         </where>
     </select>
 
+    <select id="findByNameAndHostname" 
resultType="org.apache.bigtop.manager.dao.po.ComponentPO">
+        select
+        <include refid="baseColumnsV2">
+            <property name="alias" value="comp"/>
+        </include>, s.name as service_name, s.user as service_user, 
s.display_name as service_display_name, s.stack, h.hostname
+        from
+        component comp
+        left join service s on comp.service_id = s.id
+        left join host h on comp.host_id = h.id
+        <where>
+            <if test="name != null and name != ''">
+                and comp.name = #{name}
+            </if>
+            <if test="hostname != null and hostname != ''">
+                and h.hostname = #{hostname}
+            </if>
+        </where>
+    </select>
+
     <select id="findDetailsById" 
resultType="org.apache.bigtop.manager.dao.po.ComponentPO">
         select
         <include refid="baseColumnsV2">
diff --git a/bigtop-manager-dao/src/main/resources/mapper/mysql/ToolMapper.xml 
b/bigtop-manager-dao/src/main/resources/mapper/mysql/ToolMapper.xml
new file mode 100644
index 00000000..bf95e536
--- /dev/null
+++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/ToolMapper.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ 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.
+-->
+
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd";>
+<mapper namespace="org.apache.bigtop.manager.dao.repository.ToolDao">
+
+    <sql id="baseColumns">
+        id, name, base_url, pkg_name, arch, checksum
+    </sql>
+    <sql id="baseColumnsV2">
+        ${alias}.id, ${alias}.name, ${alias}.base_url, ${alias}.pkg_name, 
${alias}.arch, ${alias}.checksum
+    </sql>
+
+    <select id="findByName" 
resultType="org.apache.bigtop.manager.dao.po.ToolPO">
+        select
+        <include refid="baseColumns"/>
+        from
+        tool
+        where name = #{name}
+        limit 1
+    </select>
+</mapper>
\ No newline at end of file
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ComponentMapper.xml 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ComponentMapper.xml
index 4f87b36e..2d5d44f4 100644
--- 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ComponentMapper.xml
+++ 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ComponentMapper.xml
@@ -80,6 +80,25 @@
         </where>
     </select>
 
+    <select id="findByNameAndHostname" 
resultType="org.apache.bigtop.manager.dao.po.ComponentPO">
+        select
+        <include refid="baseColumnsV2">
+            <property name="alias" value="comp"/>
+        </include>, s.name as service_name, s.user as service_user, 
s.display_name as service_display_name, s.stack, h.hostname
+        from
+        component comp
+        left join service s on comp.service_id = s.id
+        left join host h on comp.host_id = h.id
+        <where>
+            <if test="name != null and name != ''">
+                and comp.name = #{name}
+            </if>
+            <if test="hostname != null and hostname != ''">
+                and h.hostname = #{hostname}
+            </if>
+        </where>
+    </select>
+
     <select id="findDetailsById" 
resultType="org.apache.bigtop.manager.dao.po.ComponentPO">
         select
         <include refid="baseColumnsV2">
diff --git 
a/bigtop-manager-dao/src/main/resources/mapper/postgresql/ToolMapper.xml 
b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ToolMapper.xml
new file mode 100644
index 00000000..bf95e536
--- /dev/null
+++ b/bigtop-manager-dao/src/main/resources/mapper/postgresql/ToolMapper.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ 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.
+-->
+
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd";>
+<mapper namespace="org.apache.bigtop.manager.dao.repository.ToolDao">
+
+    <sql id="baseColumns">
+        id, name, base_url, pkg_name, arch, checksum
+    </sql>
+    <sql id="baseColumnsV2">
+        ${alias}.id, ${alias}.name, ${alias}.base_url, ${alias}.pkg_name, 
${alias}.arch, ${alias}.checksum
+    </sql>
+
+    <select id="findByName" 
resultType="org.apache.bigtop.manager.dao.po.ToolPO">
+        select
+        <include refid="baseColumns"/>
+        from
+        tool
+        where name = #{name}
+        limit 1
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/bigtop-manager-dist/src/main/assembly/assembly-server.xml 
b/bigtop-manager-dist/src/main/assembly/assembly-server.xml
index f174ae13..6695b9f6 100644
--- a/bigtop-manager-dist/src/main/assembly/assembly-server.xml
+++ b/bigtop-manager-dist/src/main/assembly/assembly-server.xml
@@ -33,6 +33,12 @@
             <fileMode>0755</fileMode>
             <directoryMode>0755</directoryMode>
         </fileSet>
+        <fileSet>
+            
<directory>${project.basedir}/../bigtop-manager-server/src/main/resources/scripts</directory>
+            <outputDirectory>scripts</outputDirectory>
+            <fileMode>0755</fileMode>
+            <directoryMode>0755</directoryMode>
+        </fileSet>
         <fileSet>
             
<directory>${project.basedir}/../bigtop-manager-server/src/main/resources</directory>
             <includes>
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/component/ComponentAddJob.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/component/ComponentAddJob.java
index 589ac326..8a33358b 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/component/ComponentAddJob.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/component/ComponentAddJob.java
@@ -23,7 +23,6 @@ import org.apache.bigtop.manager.common.enums.Command;
 import org.apache.bigtop.manager.dao.po.ComponentPO;
 import org.apache.bigtop.manager.dao.po.HostPO;
 import org.apache.bigtop.manager.dao.po.ServicePO;
-import org.apache.bigtop.manager.dao.query.ComponentQuery;
 import org.apache.bigtop.manager.server.command.helper.ComponentStageHelper;
 import org.apache.bigtop.manager.server.command.job.JobContext;
 import org.apache.bigtop.manager.server.enums.HealthyStatusEnum;
@@ -142,9 +141,7 @@ public class ComponentAddJob extends AbstractComponentJob {
     }
 
     private Boolean checkComponentInstalled(String componentName, String 
hostname) {
-        ComponentQuery query =
-                
ComponentQuery.builder().name(componentName).hostname(hostname).build();
-        List<ComponentPO> componentPOList = componentDao.findByQuery(query);
-        return componentPOList.size() == 1;
+        ComponentPO componentPO = 
componentDao.findByNameAndHostname(componentName, hostname);
+        return componentPO != null;
     }
 }
diff --git 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/HostServiceImpl.java
 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/HostServiceImpl.java
index f1d9a621..906b741f 100644
--- 
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/HostServiceImpl.java
+++ 
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/service/impl/HostServiceImpl.java
@@ -21,14 +21,15 @@ package org.apache.bigtop.manager.server.service.impl;
 import org.apache.bigtop.manager.common.constants.MessageConstants;
 import org.apache.bigtop.manager.common.shell.ShellResult;
 import org.apache.bigtop.manager.common.utils.InstanceUtils;
+import org.apache.bigtop.manager.common.utils.ProjectPathUtils;
 import org.apache.bigtop.manager.dao.po.ComponentPO;
 import org.apache.bigtop.manager.dao.po.HostPO;
-import org.apache.bigtop.manager.dao.po.RepoPO;
 import org.apache.bigtop.manager.dao.query.ComponentQuery;
 import org.apache.bigtop.manager.dao.query.HostQuery;
 import org.apache.bigtop.manager.dao.repository.ComponentDao;
 import org.apache.bigtop.manager.dao.repository.HostDao;
 import org.apache.bigtop.manager.dao.repository.RepoDao;
+import org.apache.bigtop.manager.dao.repository.ToolDao;
 import org.apache.bigtop.manager.server.enums.ApiExceptionEnum;
 import org.apache.bigtop.manager.server.enums.HealthyStatusEnum;
 import org.apache.bigtop.manager.server.enums.HostAuthTypeEnum;
@@ -55,6 +56,10 @@ import com.github.pagehelper.PageInfo;
 import lombok.extern.slf4j.Slf4j;
 
 import jakarta.annotation.Resource;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -76,6 +81,9 @@ public class HostServiceImpl implements HostService {
     @Resource
     private ComponentDao componentDao;
 
+    @Resource
+    private ToolDao toolDao;
+
     private final List<InstalledStatusVO> installedStatus = new 
CopyOnWriteArrayList<>();
 
     private final ExecutorService executorService = 
Executors.newFixedThreadPool(5);
@@ -217,9 +225,6 @@ public class HostServiceImpl implements HostService {
 
     @Override
     public Boolean installDependencies(List<HostDTO> hostDTOList) {
-        List<RepoPO> repoPOList = repoDao.findAll();
-        Map<String, RepoPO> archRepoMap = 
repoPOList.stream().collect(Collectors.toMap(RepoPO::getArch, repo -> repo));
-
         // Clear cache list
         installedStatus.clear();
 
@@ -233,7 +238,7 @@ public class HostServiceImpl implements HostService {
                 // Async install dependencies
                 executorService.submit(() -> {
                     try {
-                        installDependencies(archRepoMap, hostDTO, hostname, 
installedStatusVO);
+                        installDependencies(hostDTO, hostname, 
installedStatusVO);
                     } catch (Exception e) {
                         log.error("Unable to install dependencies on host, 
hostname: {}", hostname, e);
                         
installedStatusVO.setStatus(InstalledStatusEnum.FAILED);
@@ -251,74 +256,36 @@ public class HostServiceImpl implements HostService {
         return installedStatus;
     }
 
-    public void installDependencies(
-            Map<String, RepoPO> archRepoMap, HostDTO hostDTO, String hostname, 
InstalledStatusVO installedStatusVO) {
+    public void installDependencies(HostDTO hostDTO, String hostname, 
InstalledStatusVO installedStatusVO) {
         String path = hostDTO.getAgentDir();
-        // Get host arch
-        String arch =
-                execCommandOnRemoteHost(hostDTO, hostname, 
"arch").getOutput().trim();
-        arch = arch.equals("arm64") ? "aarch64" : arch;
-
-        // Download & Extract agent tarball
-        String repoUrl = archRepoMap.get(arch).getBaseUrl();
-        String tarballUrl = repoUrl + "/bigtop-manager-agent.tar.gz";
-        String command = "sudo mkdir -p " + path + " &&"
-                + " sudo chown -R " + hostDTO.getSshUser() + ":" + 
hostDTO.getSshUser() + " " + path
-                + " && curl -L " + tarballUrl + " | tar -xz -C " + path;
-        ShellResult result = execCommandOnRemoteHost(hostDTO, hostname, 
command);
-        if (result.getExitCode() != MessageConstants.SUCCESS_CODE) {
-            log.error(
-                    "Unable to download & extract agent tarball, hostname: {}, 
msg: {}", hostname, result.getErrMsg());
+        String repoUrl = toolDao.findByName("agent").getBaseUrl();
+        int grpcPort = hostDTO.getGrpcPort();
+
+        String command;
+        try {
+            String script = ProjectPathUtils.getServerScriptPath() + 
File.separator + "setup-agent.sh";
+            String content = Files.readString(Path.of(script));
+            command = "cat << 'EOF' > ./setup-agent.sh\n"
+                    + content
+                    + "\nEOF\n"
+                    + "chmod +x ./setup-agent.sh && ./setup-agent.sh " + path 
+ " " + repoUrl + " " + grpcPort;
+        } catch (IOException e) {
+            log.error("Unable to setup agent, hostname: {}, msg: {}", 
hostname, e.getMessage());
 
             installedStatusVO.setStatus(InstalledStatusEnum.FAILED);
-            installedStatusVO.setMessage(result.getErrMsg());
+            installedStatusVO.setMessage(e.getMessage());
             return;
         }
 
-        // Update agent conf
-        // Current only grpc port needs to be updated if it's not default port
-        if (hostDTO.getGrpcPort() != 8835) {
-            command = "sed -i 's/port: 8835/port: " + hostDTO.getGrpcPort() + 
"/' " + path
-                    + "/bigtop-manager-agent/conf/application.yml";
-            result = execCommandOnRemoteHost(hostDTO, hostname, command);
-            if (result.getExitCode() != MessageConstants.SUCCESS_CODE) {
-                log.error("Unable to update agent config, hostname: {}, msg: 
{}", hostname, result.getErrMsg());
-
-                installedStatusVO.setStatus(InstalledStatusEnum.FAILED);
-                installedStatusVO.setMessage(result.getErrMsg());
-                return;
-            }
-        }
-
-        // Run agent in background
-        command = "nohup " + path + "/bigtop-manager-agent/bin/start.sh 
--debug > /dev/null 2>&1 &";
-        result = execCommandOnRemoteHost(hostDTO, hostname, command);
+        ShellResult result = execCommandOnRemoteHost(hostDTO, hostname, 
command);
         if (result.getExitCode() != MessageConstants.SUCCESS_CODE) {
-            log.error("Unable to start agent, hostname: {}, msg: {}", 
hostname, result.getErrMsg());
+            log.error("Unable to setup agent, hostname: {}, msg: {}", 
hostname, result.getErrMsg());
 
             installedStatusVO.setStatus(InstalledStatusEnum.FAILED);
             installedStatusVO.setMessage(result.getErrMsg());
             return;
         }
 
-        // Check the process, the agent may encounter some errors and exit 
when starting
-        // So we need to wait for a while before the check
-        try {
-            Thread.sleep(10 * 1000);
-        } catch (InterruptedException e) {
-            log.error("Thread sleep interrupted", e);
-        }
-        command = "ps -ef | grep bigtop-manager-agent | grep -v grep";
-        result = execCommandOnRemoteHost(hostDTO, hostname, command);
-        if (result.getExitCode() != MessageConstants.SUCCESS_CODE
-                || !result.getOutput().contains("bigtop-manager-agent")) {
-            log.error("Unable to start agent process, hostname: {}", hostname);
-
-            installedStatusVO.setStatus(InstalledStatusEnum.FAILED);
-            installedStatusVO.setMessage("Unable to start agent, please check 
the log.");
-            return;
-        }
-
         installedStatusVO.setStatus(InstalledStatusEnum.SUCCESS);
     }
 
diff --git a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql 
b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
index e61ad4da..b2a3a549 100644
--- a/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
+++ b/bigtop-manager-server/src/main/resources/ddl/MySQL-DDL-CREATE.sql
@@ -381,6 +381,7 @@ WHERE `name` = 'DeepSeek';
 
 INSERT INTO tool (name, base_url, pkg_name, arch, checksum)
 VALUES
+('agent', 'http://your-repo/', 'bigtop-manager-agent.tar.gz', 
'x86_64,aarch64', null),
 ('jdk8', 
'https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u452-b09/',
 'OpenJDK8U-jdk_x64_linux_hotspot_8u452b09.tar.gz', 'x86_64', 
'SHA-256:9448308a21841960a591b47927cf2d44fdc4c0533a5f8111a4b243a6bafb5d27'),
 ('jdk8', 
'https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u452-b09/',
 'OpenJDK8U-jdk_aarch64_linux_hotspot_8u452b09.tar.gz', 'aarch64', 
'SHA-256:d8a1aecea0913b7a1e0d737ba6f7ea99059b3f6fd17813d4a24e8b3fc3aee278'),
 ('mysql-connector-j', 
'https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/', 
'mysql-connector-j-8.0.33.jar', 'x86_64,aarch64', 
'SHA-256:e2a3b2fc726a1ac64e998585db86b30fa8bf3f706195b78bb77c5f99bf877bd9');
diff --git 
a/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql 
b/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
index 7aa0862f..1552e1a1 100644
--- a/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
+++ b/bigtop-manager-server/src/main/resources/ddl/PostgreSQL-DDL-CREATE.sql
@@ -391,6 +391,7 @@ WHERE "name" = 'DeepSeek';
 
 INSERT INTO tool (name, base_url, pkg_name, arch, checksum)
 VALUES
+('agent', 'http://your-repo/', 'bigtop-manager-agent.tar.gz', 
'x86_64,aarch64', null),
 ('jdk8', 
'https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u452-b09/',
 'OpenJDK8U-jdk_x64_linux_hotspot_8u452b09.tar.gz', 'x86_64', 
'SHA-256:9448308a21841960a591b47927cf2d44fdc4c0533a5f8111a4b243a6bafb5d27'),
 ('jdk8', 
'https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u452-b09/',
 'OpenJDK8U-jdk_aarch64_linux_hotspot_8u452b09.tar.gz', 'aarch64', 
'SHA-256:d8a1aecea0913b7a1e0d737ba6f7ea99059b3f6fd17813d4a24e8b3fc3aee278'),
 ('mysql-connector-j', 
'https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/', 
'mysql-connector-j-8.0.33.jar', 'x86_64,aarch64', 
'SHA-256:e2a3b2fc726a1ac64e998585db86b30fa8bf3f706195b78bb77c5f99bf877bd9');
diff --git a/bigtop-manager-server/src/main/resources/scripts/setup-agent.sh 
b/bigtop-manager-server/src/main/resources/scripts/setup-agent.sh
new file mode 100644
index 00000000..c26a592c
--- /dev/null
+++ b/bigtop-manager-server/src/main/resources/scripts/setup-agent.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+#
+# 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
+#
+#    https://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.
+#
+
+set -e
+
+[ $# -lt 3 ] && {
+    echo "Usage: $0 <dir_prefix> <repo_url> <grpc_port> [checksum_alg 
checksum_value]" >&2
+    exit 1
+}
+
+USER=$(whoami)
+GROUP=$(id -gn)
+
+check_sudo() {
+    if ! sudo -n true 2>/dev/null; then
+        echo "ERROR: User '$USER' doesn't have sudo privileges" >&2
+        exit 1
+    fi
+}
+
+check_sudo
+
+DIR_PREFIX="$1"
+REPO_URL="$2"
+GRPC_PORT="$3"
+CHECK_ALG="${4:-}"
+CHECK_VAL="${5:-}"
+
+TAR_FILE="${DIR_PREFIX}/bigtop-manager-agent.tar.gz"
+TARGET_DIR="${DIR_PREFIX}/bigtop-manager-agent"
+DOWNLOAD_URL="${REPO_URL}/bigtop-manager-agent.tar.gz"
+PROCESS_NAME="org.apache.bigtop.manager.agent.AgentApplication"
+
+validate_checksum() {
+    local file="$1"
+    case "${CHECK_ALG}" in
+        MD5)   sum_cmd="md5sum" ;;
+        SHA-1)  sum_cmd="sha1sum" ;;
+        SHA-256) sum_cmd="sha256sum" ;;
+        *) return 0 ;;  # Skip validation if no algorithm specified
+    esac
+
+    local calc_val=$($sum_cmd "$file" | awk '{print $1}')
+    [ "$calc_val" = "$CHECK_VAL" ] || {
+        echo "Checksum mismatch: Expected ${CHECK_ALG}=$CHECK_VAL, 
Found=$calc_val" >&2
+        return 1
+    }
+}
+
+# File handling with validation
+handle_tar_file() {
+    # Validate existing file
+    if [ -f "$TAR_FILE" ]; then
+        if [ -n "$CHECK_ALG" ]; then
+            validate_checksum "$TAR_FILE" || {
+                echo "Removing invalid file: $TAR_FILE" >&2
+                rm -f "$TAR_FILE"
+                return 1
+            }
+        fi
+        return 0
+    fi
+
+    # Download file
+    if command -v wget &> /dev/null; then
+        wget "$DOWNLOAD_URL" -O "$TAR_FILE"
+    else
+        curl -L "$DOWNLOAD_URL" -o "$TAR_FILE"
+    fi
+
+    # Post-download validation
+    if [ -n "$CHECK_ALG" ]; then
+      echo "Validating checksum"
+      validate_checksum "$TAR_FILE" || {
+          rm -f "$TAR_FILE"
+          echo "Downloaded file checksum validation failed" >&2
+          exit 1
+      }
+    fi
+}
+
+deploy_agent() {
+    [ -d "$TARGET_DIR" ] && return 0
+    handle_tar_file
+    sudo mkdir -p "${TARGET_DIR}"
+    sudo chown -R ${USER}:${GROUP} "${TARGET_DIR}"
+    tar -zxf "${TAR_FILE}" -C "${TARGET_DIR}" --strip-components=1
+}
+
+start() {
+    export GRPC_PORT="$GRPC_PORT"
+
+    if ! pgrep -f "${PROCESS_NAME}" > /dev/null; then
+        nohup ${TARGET_DIR}/bin/start.sh --debug > /dev/null 2>&1 &
+        sleep 10
+        pgrep -f "${PROCESS_NAME}" > /dev/null || exit 1
+    fi
+}
+
+deploy_agent
+start
diff --git a/dev-support/docker/containers/build.sh 
b/dev-support/docker/containers/build.sh
index eac7039e..018f6d66 100755
--- a/dev-support/docker/containers/build.sh
+++ b/dev-support/docker/containers/build.sh
@@ -48,14 +48,13 @@ build() {
 
 destroy() {
   log "Destroy Containers!!!"
-  docker rm -f $(docker network inspect bigtop-manager -f '{{range 
.Containers}}{{.Name}}{{" "}}{{end}}')
-  docker network rm bigtop-manager
+  docker rm -f $(docker ps -q --filter network=bigtop-manager --filter 
"name=^bm-")
   exit 0
 }
 
 create() {
   log "Create Containers!!!"
-  docker network create --driver bridge bigtop-manager
+  docker network inspect bigtop-manager >/dev/null 2>&1 || docker network 
create --driver bridge bigtop-manager
   create_db
   create_container
 }
@@ -75,6 +74,7 @@ create_container() {
       docker run -itd --name ${container_name} --hostname ${container_name} 
--network bigtop-manager --cap-add=SYS_TIME bigtop-manager/develop:${OS}
     fi
 
+    docker cp 
../../../bigtop-manager-dist/target/apache-bigtop-manager-*-agent.tar.gz 
${container_name}:/opt/bigtop-manager-agent.tar.gz
     docker exec ${container_name} bash -c "mkdir -p /root/.ssh && echo 
'$SERVER_PUB_KEY' > /root/.ssh/authorized_keys"
     docker exec ${container_name} ssh-keygen -N '' -t rsa -b 2048 -f 
/etc/ssh/ssh_host_rsa_key
     docker exec ${container_name} ssh-keygen -N '' -t ecdsa -b 256 -f 
/etc/ssh/ssh_host_ecdsa_key

Reply via email to