You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2021/12/28 11:44:55 UTC

[incubator-doris] branch doris-manager updated: [Manager] Support install broker and install rollback (#7508)

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

morningman pushed a commit to branch doris-manager
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/doris-manager by this push:
     new 5c12498  [Manager] Support install broker and install rollback (#7508)
5c12498 is described below

commit 5c12498bcb8730a5eb8f82a5b8cbbeb5d6bf57ac
Author: weajun <we...@gmail.com>
AuthorDate: Tue Dec 28 19:44:37 2021 +0800

    [Manager] Support install broker and install rollback (#7508)
    
    1.Install broker by default when deploying a new cluster.
    2.Support some steps in the installation process to be able to go back to the previous step.
    3.Support the installation page to automatically jump to the steps in the last installation.
---
 .../doris/manager/agent/api/CommonControllder.java |   4 +
 .../manager/agent/command/BeInstallCommand.java    |   4 -
 .../manager/agent/command/BeStartCommand.java      |  19 +++-
 .../manager/agent/command/BrokerStartCommand.java  |  16 +++-
 .../manager/agent/command/CommandFactory.java      |   6 +-
 .../manager/agent/command/FeInstallCommand.java    |   5 -
 .../manager/agent/command/FeStartCommand.java      |  16 ++--
 .../manager/agent/command/WriteBeConfCommand.java  |   2 +-
 .../manager/agent/command/WriteFeConfCommand.java  |   2 +-
 .../doris/manager/agent/common/AgentConstants.java |   4 +-
 .../doris/manager/agent/service/BeService.java     |  19 ++--
 .../doris/manager/agent/service/FeService.java     |   6 +-
 .../doris/manager/agent/task/ScriptTask.java       |   4 +-
 manager/dm-common/pom.xml                          |   2 +-
 ...estBody.java => BeStartCommandRequestBody.java} |  12 +--
 ...ody.java => BrokerStartCommandRequestBody.java} |  12 +--
 .../common/domain/FeStartCommandRequestBody.java   |   9 ++
 manager/dm-server/pom.xml                          |   2 +-
 .../org/apache/doris/stack/agent/AgentCache.java   |   6 ++
 .../stack/component/TaskInstanceComponent.java     |  10 +-
 .../apache/doris/stack/constants/Constants.java    |   3 +
 .../doris/stack/constants/ProcessTypeEnum.java     |   7 +-
 .../stack/controller/ProcessTaskController.java    |  23 +++--
 .../doris/stack/entity/ProcessInstanceEntity.java  |  13 +++
 .../doris/stack/entity/TaskInstanceEntity.java     |  20 +++-
 .../stack/model/response/CurrentProcessResp.java}  |  37 ++++++--
 .../stack/model/response/TaskInstanceResp.java     |  64 +++++++++++++
 .../doris/stack/runner/TaskExecuteThread.java      |   3 -
 .../apache/doris/stack/service/ProcessTask.java    |   8 +-
 .../doris/stack/service/impl/AgentProcessImpl.java | 103 ++++++++++++++++-----
 .../doris/stack/service/impl/ProcessTaskImpl.java  |  55 +++++++++--
 .../stack/service/impl/ServerProcessImpl.java      |  14 ++-
 .../org/apache/doris/stack/task/JoinBeTask.java    |  81 ----------------
 ...216\245\345\217\243\346\226\207\346\241\243.md" |  57 +++++++++++-
 34 files changed, 440 insertions(+), 208 deletions(-)

diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/api/CommonControllder.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/api/CommonControllder.java
index 8489481..e22797e 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/api/CommonControllder.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/api/CommonControllder.java
@@ -19,6 +19,7 @@ package org.apache.doris.manager.agent.api;
 
 import org.apache.doris.manager.agent.register.AgentContext;
 import org.apache.doris.manager.agent.service.BeService;
+import org.apache.doris.manager.agent.service.BrokerService;
 import org.apache.doris.manager.agent.service.FeService;
 import org.apache.doris.manager.agent.service.Service;
 import org.apache.doris.manager.agent.service.ServiceContext;
@@ -74,6 +75,9 @@ public class CommonControllder {
         } else if (ServiceRole.findByName(register.getRole()) == ServiceRole.BE) {
             BeService beService = new BeService(register.getInstallDir());
             ServiceContext.register(beService);
+        } else if (ServiceRole.findByName(register.getRole()) == ServiceRole.BROKER) {
+            BrokerService brokerService = new BrokerService(register.getInstallDir());
+            ServiceContext.register(brokerService);
         } else {
             return RResult.error("unkown service role");
         }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeInstallCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeInstallCommand.java
index 1595e03..e025c39 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeInstallCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeInstallCommand.java
@@ -106,10 +106,6 @@ public class BeInstallCommand extends Command {
         @Override
         public void onSuccess(BeInstallTaskDesc taskDesc) {
             BeService beService = new BeService(taskDesc.getInstallDir());
-            if (taskDesc.isCreateBeStorageDir()) {
-                beService.createStrorageDir(false);
-            }
-
             ServiceContext.register(beService);
         }
     }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeStartCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeStartCommand.java
index 0b96390..3a811da 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeStartCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BeStartCommand.java
@@ -25,16 +25,29 @@ import org.apache.doris.manager.agent.task.ScriptTask;
 import org.apache.doris.manager.agent.task.ScriptTaskDesc;
 import org.apache.doris.manager.agent.task.Task;
 import org.apache.doris.manager.agent.task.TaskHandlerFactory;
+import org.apache.doris.manager.common.domain.BeStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.CommandType;
 import org.apache.doris.manager.common.domain.ServiceRole;
 
+import java.util.Objects;
+
 public class BeStartCommand extends BeCommand {
+    private BeStartCommandRequestBody requestBody;
+
+    public BeStartCommand(BeStartCommandRequestBody requestBody) {
+        this.requestBody = requestBody;
+    }
+
     @Override
     public Task setupTask() {
+        String scriptCmd = "";
         ScriptTaskDesc taskDesc = new ScriptTaskDesc();
-
-        String scriptCmd = AgentConstants.BASH_BIN;
-        scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.BE).getInstallDir() + "/bin/start_be.sh --daemon";
+        if (Objects.nonNull(requestBody) && requestBody.isStopBeforeStart()) {
+            scriptCmd += AgentConstants.BASH_BIN;
+            scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.BE).getInstallDir() + "/bin/stop_be.sh ;";
+        }
+        scriptCmd += "cd " + ServiceContext.getServiceMap().get(ServiceRole.BE).getInstallDir() + " && ";
+        scriptCmd += AgentConstants.BASH_BIN + "./bin/start_be.sh --daemon";
         taskDesc.setScriptCmd(scriptCmd);
         return new ScriptTask(taskDesc);
     }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BrokerStartCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BrokerStartCommand.java
index befd875..9ac62e3 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BrokerStartCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/BrokerStartCommand.java
@@ -25,15 +25,29 @@ import org.apache.doris.manager.agent.task.ScriptTask;
 import org.apache.doris.manager.agent.task.ScriptTaskDesc;
 import org.apache.doris.manager.agent.task.Task;
 import org.apache.doris.manager.agent.task.TaskHandlerFactory;
+import org.apache.doris.manager.common.domain.BrokerStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.CommandType;
 import org.apache.doris.manager.common.domain.ServiceRole;
 
+import java.util.Objects;
+
 public class BrokerStartCommand extends BrokerCommand {
+    private BrokerStartCommandRequestBody requestBody;
+
+    public BrokerStartCommand(BrokerStartCommandRequestBody requestBody) {
+        this.requestBody = requestBody;
+    }
+
     @Override
     public Task setupTask() {
+        String scriptCmd = "";
         ScriptTaskDesc taskDesc = new ScriptTaskDesc();
+        if (Objects.nonNull(requestBody) && requestBody.isStopBeforeStart()) {
+            scriptCmd += AgentConstants.BASH_BIN;
+            scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.BROKER).getInstallDir() + "/bin/stop_broker.sh ;";
+        }
 
-        String scriptCmd = AgentConstants.BASH_BIN;
+        scriptCmd += AgentConstants.BASH_BIN;
         scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.BROKER).getInstallDir() + "/bin/start_broker.sh --daemon";
         taskDesc.setScriptCmd(scriptCmd);
         return new ScriptTask(taskDesc);
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/CommandFactory.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/CommandFactory.java
index 975f6ca..5423a1f 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/CommandFactory.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/CommandFactory.java
@@ -20,7 +20,9 @@ package org.apache.doris.manager.agent.command;
 import com.alibaba.fastjson.JSON;
 import org.apache.doris.manager.agent.exception.AgentException;
 import org.apache.doris.manager.common.domain.BeInstallCommandRequestBody;
+import org.apache.doris.manager.common.domain.BeStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.BrokerInstallCommandRequestBody;
+import org.apache.doris.manager.common.domain.BrokerStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.CommandRequest;
 import org.apache.doris.manager.common.domain.CommandType;
 import org.apache.doris.manager.common.domain.FeInstallCommandRequestBody;
@@ -61,11 +63,11 @@ public class CommandFactory {
             case STOP_FE:
                 return new FeStopCommand();
             case START_BE:
-                return new BeStartCommand();
+                return new BeStartCommand(JSON.parseObject(body, BeStartCommandRequestBody.class));
             case STOP_BE:
                 return new BeStopCommand();
             case START_BROKER:
-                return new BrokerStartCommand();
+                return new BrokerStartCommand(JSON.parseObject(body, BrokerStartCommandRequestBody.class));
             case STOP_BROKER:
                 return new BrokerStopCommand();
             case WRITE_FE_CONF:
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeInstallCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeInstallCommand.java
index 5c04d21..aa2c7e3 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeInstallCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeInstallCommand.java
@@ -109,11 +109,6 @@ public class FeInstallCommand extends Command {
         @Override
         public void onSuccess(FeInstallTaskDesc taskDesc) {
             FeService feService = new FeService(taskDesc.getInstallDir());
-
-            if (taskDesc.isCreateMetaDir()) {
-                feService.createMetaDir(false);
-            }
-
             ServiceContext.register(feService);
         }
     }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeStartCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeStartCommand.java
index dd4f7a0..d6299fe 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeStartCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/FeStartCommand.java
@@ -41,13 +41,17 @@ public class FeStartCommand extends FeCommand {
     @Override
     public Task setupTask() {
         ScriptTaskDesc taskDesc = new ScriptTaskDesc();
+        String scriptCmd = "";
 
-        String scriptCmd = AgentConstants.BASH_BIN;
-        scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.FE).getInstallDir() + "/bin/start_fe.sh ";
-        if (Objects.nonNull(requestBody)) {
-            if (Objects.nonNull(requestBody.getHelpHostPort()) && requestBody.getHelpHostPort().length() > 0) {
-                scriptCmd += " --help " + requestBody.getHelpHostPort();
-            }
+        if (Objects.nonNull(requestBody) && requestBody.isStopBeforeStart()) {
+            scriptCmd += AgentConstants.BASH_BIN;
+            scriptCmd += ServiceContext.getServiceMap().get(ServiceRole.FE).getInstallDir() + "/bin/stop_fe.sh ; ";
+        }
+
+        scriptCmd += "cd " + ServiceContext.getServiceMap().get(ServiceRole.FE).getInstallDir() + " && ";
+        scriptCmd += AgentConstants.BASH_BIN + "./bin/start_fe.sh ";
+        if (Objects.nonNull(requestBody) && Objects.nonNull(requestBody.getHelpHostPort()) && requestBody.getHelpHostPort().length() > 0) {
+            scriptCmd += " --help " + requestBody.getHelpHostPort();
         }
         scriptCmd += " --daemon";
         taskDesc.setScriptCmd(scriptCmd);
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteBeConfCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteBeConfCommand.java
index f2160d0..df4d183 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteBeConfCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteBeConfCommand.java
@@ -96,7 +96,7 @@ public class WriteBeConfCommand extends BeCommand {
             service.load();
 
             if (taskDesc.isCreateStorageDir()) {
-                service.createStrorageDir(true);
+                service.createStrorageDir();
             }
         }
     }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteFeConfCommand.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteFeConfCommand.java
index 3b2c6d2..eca53ba 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteFeConfCommand.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/command/WriteFeConfCommand.java
@@ -96,7 +96,7 @@ public class WriteFeConfCommand extends FeCommand {
             FeService service = (FeService) ServiceContext.getServiceMap().get(ServiceRole.FE);
             service.load();
             if (taskDesc.isCreateMetaDir()) {
-                service.createMetaDir(true);
+                service.createMetaDir();
             }
         }
     }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/common/AgentConstants.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/common/AgentConstants.java
index 60b4bfb..7e549a7 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/common/AgentConstants.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/common/AgentConstants.java
@@ -25,7 +25,7 @@ public class AgentConstants {
 
     public static final int COMMAND_HISTORY_SAVE_MAX_COUNT = 100;
 
-    public static final String BASH_BIN = "/bin/sh ";
+    public static final String BASH_BIN = " /bin/bash ";
 
     public static final String FE_CONFIG_KEY_META_DIR = "meta_dir";
     public static final String BE_CONFIG_KEY_STORAGE_DIR = "storage_root_path";
@@ -33,8 +33,6 @@ public class AgentConstants {
     public static final String BE_CONFIG_KEY_HTTP_PORT = "webserver_port";
     public static final String BROKER_CONFIG_KEY_IPC_PORT = "broker_ipc_port";
 
-    public static final String FE_DEFAULT_META_DIR_RELATIVE_PATH = "/doris-meta";
-    public static final String BE_DEFAULT_STORAGE_DIR_RELATIVE_PATH = "/storage";
     public static final String FE_CONFIG_FILE_RELATIVE_PATH = "/conf/fe.conf";
     public static final String BE_CONFIG_FILE_RELATIVE_PATH = "/conf/be.conf";
     public static final String BROKER_CONFIG_FILE_RELATIVE_PATH = "/conf/apache_hdfs_broker.conf";
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/BeService.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/BeService.java
index ae85962..3c749d4 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/BeService.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/BeService.java
@@ -19,7 +19,6 @@ package org.apache.doris.manager.agent.service;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import lombok.extern.slf4j.Slf4j;
 import org.apache.doris.manager.agent.common.AgentConstants;
 import org.apache.doris.manager.agent.exception.AgentException;
 import org.apache.doris.manager.agent.register.AgentContext;
@@ -30,6 +29,8 @@ import org.apache.http.client.methods.HttpGet;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
@@ -37,9 +38,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
-@Slf4j
 public class BeService extends Service {
 
+    private static final Logger TASKLOG = LoggerFactory.getLogger(AgentConstants.LOG_TYPE_TASK);
+
     public BeService(String installDir) {
         super(ServiceRole.BE, installDir, installDir + AgentConstants.BE_CONFIG_FILE_RELATIVE_PATH);
         doLoad();
@@ -53,9 +55,9 @@ public class BeService extends Service {
                 continue;
             }
 
-            int lastIndex = split.lastIndexOf(".");
+            int lastIndex = split.indexOf(",");
             if (lastIndex == -1) {
-                list.add(split.substring(0));
+                list.add(split);
             } else {
                 list.add(split.substring(0, lastIndex));
             }
@@ -109,7 +111,7 @@ public class BeService extends Service {
         return false;
     }
 
-    public void createStrorageDir(boolean createDefaultMetaDir) {
+    public void createStrorageDir() {
         String storageVal = null;
         String storageValInConfig = getConfig().getProperty(AgentConstants.BE_CONFIG_KEY_STORAGE_DIR);
         if (Objects.nonNull(storageValInConfig) && storageValInConfig.contains("${DORIS_HOME}/")) {
@@ -120,8 +122,9 @@ public class BeService extends Service {
             storageVal = installDir + subDir;
         } else if (Objects.nonNull(storageValInConfig) && storageValInConfig.startsWith("/")) {
             storageVal = storageValInConfig;
-        } else if (createDefaultMetaDir) {
-            storageVal = installDir + AgentConstants.BE_DEFAULT_STORAGE_DIR_RELATIVE_PATH;
+        } else {
+            TASKLOG.info("be storage path must be start ${DORIS_HOME} or /,path={}", storageVal);
+            throw new AgentException("parse be storage path failed");
         }
 
         if (Objects.nonNull(storageVal)) {
@@ -130,7 +133,7 @@ public class BeService extends Service {
                 File file = new File(dir);
                 if (!file.exists()) {
                     boolean r = file.mkdirs();
-                    log.info("create storage path:{},ret:{}", dir, r);
+                    TASKLOG.info("create storage path:{},ret:{}", dir, r);
                 }
             }
         }
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/FeService.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/FeService.java
index f63574a..f4449e6 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/FeService.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/service/FeService.java
@@ -92,7 +92,7 @@ public class FeService extends Service {
         return false;
     }
 
-    public void createMetaDir(boolean createDefaultMetaDir) {
+    public void createMetaDir() {
         String dir = null;
         String metaDir = getConfig().getProperty(AgentConstants.FE_CONFIG_KEY_META_DIR);
         if (Objects.nonNull(metaDir) && metaDir.contains("${DORIS_HOME}/")) {
@@ -103,8 +103,8 @@ public class FeService extends Service {
             dir = installDir + subDir;
         } else if (Objects.nonNull(metaDir) && metaDir.startsWith("/")) {
             dir = metaDir;
-        } else if (createDefaultMetaDir) {
-            dir = installDir + AgentConstants.FE_DEFAULT_META_DIR_RELATIVE_PATH;
+        } else {
+            dir = installDir + File.separator + metaDir;
         }
 
         if (Objects.nonNull(dir)) {
diff --git a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/task/ScriptTask.java b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/task/ScriptTask.java
index 53e8ee5..815bbed 100644
--- a/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/task/ScriptTask.java
+++ b/manager/dm-agent/src/main/java/org/apache/doris/manager/agent/task/ScriptTask.java
@@ -40,7 +40,9 @@ public class ScriptTask extends Task<ScriptTaskDesc> {
     @Override
     protected int execute() throws IOException, InterruptedException {
         Runtime rt = Runtime.getRuntime();
-        Process proc = rt.exec(taskDesc.getScriptCmd());
+        String[] commands = {"/bin/bash", "-c", ""};
+        commands[2] = taskDesc.getScriptCmd();
+        Process proc = rt.exec(commands);
         BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
         BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
 
diff --git a/manager/dm-common/pom.xml b/manager/dm-common/pom.xml
index 9446282..a7c8c75 100644
--- a/manager/dm-common/pom.xml
+++ b/manager/dm-common/pom.xml
@@ -10,6 +10,6 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>dm-common</artifactId>
-<!--    <packaging>jar</packaging>-->
+    <!--    <packaging>jar</packaging>-->
 
 </project>
\ No newline at end of file
diff --git a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BeStartCommandRequestBody.java
similarity index 76%
copy from manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
copy to manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BeStartCommandRequestBody.java
index 7410032..aa9b763 100644
--- a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
+++ b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BeStartCommandRequestBody.java
@@ -17,14 +17,14 @@
 
 package org.apache.doris.manager.common.domain;
 
-public class FeStartCommandRequestBody {
-    private String helpHostPort;
+public class BeStartCommandRequestBody {
+    private boolean stopBeforeStart;
 
-    public String getHelpHostPort() {
-        return helpHostPort;
+    public boolean isStopBeforeStart() {
+        return stopBeforeStart;
     }
 
-    public void setHelpHostPort(String helpHostPort) {
-        this.helpHostPort = helpHostPort;
+    public void setStopBeforeStart(boolean stopBeforeStart) {
+        this.stopBeforeStart = stopBeforeStart;
     }
 }
diff --git a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BrokerStartCommandRequestBody.java
similarity index 76%
copy from manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
copy to manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BrokerStartCommandRequestBody.java
index 7410032..50cb444 100644
--- a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
+++ b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/BrokerStartCommandRequestBody.java
@@ -17,14 +17,14 @@
 
 package org.apache.doris.manager.common.domain;
 
-public class FeStartCommandRequestBody {
-    private String helpHostPort;
+public class BrokerStartCommandRequestBody {
+    private boolean stopBeforeStart;
 
-    public String getHelpHostPort() {
-        return helpHostPort;
+    public boolean isStopBeforeStart() {
+        return stopBeforeStart;
     }
 
-    public void setHelpHostPort(String helpHostPort) {
-        this.helpHostPort = helpHostPort;
+    public void setStopBeforeStart(boolean stopBeforeStart) {
+        this.stopBeforeStart = stopBeforeStart;
     }
 }
diff --git a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
index 7410032..2e6a7c8 100644
--- a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
+++ b/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
@@ -19,6 +19,7 @@ package org.apache.doris.manager.common.domain;
 
 public class FeStartCommandRequestBody {
     private String helpHostPort;
+    private boolean stopBeforeStart;
 
     public String getHelpHostPort() {
         return helpHostPort;
@@ -27,4 +28,12 @@ public class FeStartCommandRequestBody {
     public void setHelpHostPort(String helpHostPort) {
         this.helpHostPort = helpHostPort;
     }
+
+    public boolean isStopBeforeStart() {
+        return stopBeforeStart;
+    }
+
+    public void setStopBeforeStart(boolean stopBeforeStart) {
+        this.stopBeforeStart = stopBeforeStart;
+    }
 }
diff --git a/manager/dm-server/pom.xml b/manager/dm-server/pom.xml
index dec0b43..51db1db 100644
--- a/manager/dm-server/pom.xml
+++ b/manager/dm-server/pom.xml
@@ -10,7 +10,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>dm-server</artifactId>
-<!--    <packaging>jar</packaging>-->
+    <!--    <packaging>jar</packaging>-->
 
     <name>dm-server</name>
 
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/agent/AgentCache.java b/manager/dm-server/src/main/java/org/apache/doris/stack/agent/AgentCache.java
index f550e6b..988eca8 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/agent/AgentCache.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/agent/AgentCache.java
@@ -95,4 +95,10 @@ public class AgentCache {
         }
         return agent.getPort();
     }
+
+    public void refresh(List<AgentEntity> agentEntities) {
+        hostAgentCache.clear();
+        Map<String, AgentEntity> agentsMap = agentEntities.stream().collect(Collectors.toMap(AgentEntity::getHost, v -> v, (v1, v2) -> v1));
+        hostAgentCache.putAll(agentsMap);
+    }
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/component/TaskInstanceComponent.java b/manager/dm-server/src/main/java/org/apache/doris/stack/component/TaskInstanceComponent.java
index 4d4f6ff..d976613 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/component/TaskInstanceComponent.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/component/TaskInstanceComponent.java
@@ -109,14 +109,10 @@ public class TaskInstanceComponent {
     }
 
     /**
-     * Check whether the parent task is successful
+     * Check whether the task is successful
      */
-    public boolean checkParentTaskSuccess(int processId, ProcessTypeEnum processType) {
-        ProcessTypeEnum parent = ProcessTypeEnum.findParent(processType);
-        if (parent == null) {
-            return true;
-        }
-        List<TaskInstanceEntity> taskInstanceEntities = taskInstanceRepository.queryTasksByProcessStep(processId, parent);
+    public boolean checkTaskSuccess(int processId, ProcessTypeEnum processType) {
+        List<TaskInstanceEntity> taskInstanceEntities = taskInstanceRepository.queryTasksByProcessStep(processId, processType);
         if (ObjectUtils.isEmpty(taskInstanceEntities)) {
             log.error("parent step {} has no task", processType.name());
             return false;
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/constants/Constants.java b/manager/dm-server/src/main/java/org/apache/doris/stack/constants/Constants.java
index 351ebf7..81703d4 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/constants/Constants.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/constants/Constants.java
@@ -30,4 +30,7 @@ public class Constants {
     public static final Integer DORIS_DEFAULT_FE_QUERY_PORT = 9030;
     public static final Integer DORIS_DEFAULT_FE_EDIT_LOG_PORT = 9010;
     public static final Integer DORIS_DEFAULT_BROKER_IPC_PORT = 8000;
+
+    public static final String BE_EXIST_MSG = "Same backend already exists";
+
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/constants/ProcessTypeEnum.java b/manager/dm-server/src/main/java/org/apache/doris/stack/constants/ProcessTypeEnum.java
index 069a3e1..d53cfba 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/constants/ProcessTypeEnum.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/constants/ProcessTypeEnum.java
@@ -24,8 +24,7 @@ public enum ProcessTypeEnum {
     INSTALL_AGENT(0, "install agent"),
     INSTALL_SERVICE(1, "install service"),
     DEPLOY_CONFIG(2, "deploy config"),
-    START_SERVICE(3, "start service"),
-    BUILD_CLUSTER(4, "build cluster");
+    START_SERVICE(3, "start service");
 
     private int code;
     private String desc;
@@ -62,6 +61,10 @@ public enum ProcessTypeEnum {
         }
     }
 
+    public boolean endProcess() {
+        return this == START_SERVICE;
+    }
+
     public int getCode() {
         return code;
     }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/controller/ProcessTaskController.java b/manager/dm-server/src/main/java/org/apache/doris/stack/controller/ProcessTaskController.java
index 54deba2..2ded928 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/controller/ProcessTaskController.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/controller/ProcessTaskController.java
@@ -20,8 +20,9 @@ package org.apache.doris.stack.controller;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.doris.manager.common.domain.RResult;
-import org.apache.doris.stack.entity.ProcessInstanceEntity;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
+import org.apache.doris.stack.model.response.CurrentProcessResp;
+import org.apache.doris.stack.model.response.TaskInstanceResp;
 import org.apache.doris.stack.service.ProcessTask;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -45,12 +46,12 @@ public class ProcessTaskController {
     private ProcessTask processTask;
 
     /**
-     * query user history installation progress
+     * query user current installation progress
      */
-    @ApiOperation(value = "query user history installation progress")
-    @RequestMapping(value = "/historyProgress", method = RequestMethod.GET)
-    public RResult historyProgress(HttpServletRequest request, HttpServletResponse response) throws Exception {
-        ProcessInstanceEntity process = processTask.historyProgress(request, response);
+    @ApiOperation(value = "query user current installation process")
+    @RequestMapping(value = "/currentProcess", method = RequestMethod.GET)
+    public RResult currentProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        CurrentProcessResp process = processTask.currentProcess(request, response);
         return RResult.success(process);
     }
 
@@ -72,7 +73,7 @@ public class ProcessTaskController {
     @RequestMapping(value = "/{processId}/currentTasks", method = RequestMethod.GET)
     public RResult taskProgress(HttpServletRequest request, HttpServletResponse response,
                                 @PathVariable(value = "processId") int processId) {
-        List<TaskInstanceEntity> tasks = processTask.taskProgress(request, response, processId);
+        List<TaskInstanceResp> tasks = processTask.taskProgress(request, response, processId);
         return RResult.success(tasks);
     }
 
@@ -134,4 +135,12 @@ public class ProcessTaskController {
         return RResult.success(processTask.taskLog(taskId));
     }
 
+    /**
+     * Go back to the previous step
+     */
+    @RequestMapping(value = "/back/{processId}", method = RequestMethod.POST)
+    public RResult backPrevious(@PathVariable int processId) {
+        processTask.backPrevious(processId);
+        return RResult.success();
+    }
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/entity/ProcessInstanceEntity.java b/manager/dm-server/src/main/java/org/apache/doris/stack/entity/ProcessInstanceEntity.java
index 6321ce9..ff3b338 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/entity/ProcessInstanceEntity.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/entity/ProcessInstanceEntity.java
@@ -23,6 +23,7 @@ import lombok.NoArgsConstructor;
 import org.apache.doris.stack.constants.ExecutionStatus;
 import org.apache.doris.stack.constants.Flag;
 import org.apache.doris.stack.constants.ProcessTypeEnum;
+import org.apache.doris.stack.model.response.CurrentProcessResp;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -89,4 +90,16 @@ public class ProcessInstanceEntity {
         this.finish = Flag.NO;
         this.status = ExecutionStatus.RUNNING;
     }
+
+    public CurrentProcessResp transToCurrentResp() {
+        CurrentProcessResp processResp = new CurrentProcessResp();
+        processResp.setId(id);
+        processResp.setClusterId(clusterId);
+        processResp.setProcessType(processType);
+        processResp.setProcessStep(processType.getCode());
+        processResp.setCreateTime(createTime);
+        processResp.setUpdateTime(updateTime);
+        processResp.setStatus(status);
+        return processResp;
+    }
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/entity/TaskInstanceEntity.java b/manager/dm-server/src/main/java/org/apache/doris/stack/entity/TaskInstanceEntity.java
index 0d07fb1..5f3fa54 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/entity/TaskInstanceEntity.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/entity/TaskInstanceEntity.java
@@ -24,6 +24,7 @@ import org.apache.doris.stack.constants.ExecutionStatus;
 import org.apache.doris.stack.constants.Flag;
 import org.apache.doris.stack.constants.ProcessTypeEnum;
 import org.apache.doris.stack.constants.TaskTypeEnum;
+import org.apache.doris.stack.model.response.TaskInstanceResp;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -90,10 +91,6 @@ public class TaskInstanceEntity {
     @Column(name = "skip", nullable = false)
     private Flag skip;
 
-    private String taskRole;
-
-    private String response;
-
     public TaskInstanceEntity(int processId, String host, ProcessTypeEnum processType, TaskTypeEnum taskType, ExecutionStatus status) {
         this.processId = processId;
         this.host = host;
@@ -121,4 +118,19 @@ public class TaskInstanceEntity {
         this.finish = Flag.NO;
         this.skip = Flag.NO;
     }
+
+    public TaskInstanceResp transToModel() {
+        TaskInstanceResp taskResp = new TaskInstanceResp();
+        taskResp.setId(id);
+        taskResp.setProcessId(processId);
+        taskResp.setHost(host);
+        taskResp.setProcessType(processType);
+        taskResp.setTaskType(taskType);
+        taskResp.setStatus(status);
+        taskResp.setStartTime(startTime);
+        taskResp.setEndTime(endTime);
+        taskResp.setFinish(finish);
+        taskResp.setSkip(skip);
+        return taskResp;
+    }
 }
diff --git a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java b/manager/dm-server/src/main/java/org/apache/doris/stack/model/response/CurrentProcessResp.java
similarity index 56%
copy from manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
copy to manager/dm-server/src/main/java/org/apache/doris/stack/model/response/CurrentProcessResp.java
index 7410032..a53972c 100644
--- a/manager/dm-common/src/main/java/org/apache/doris/manager/common/domain/FeStartCommandRequestBody.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/model/response/CurrentProcessResp.java
@@ -15,16 +15,35 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.manager.common.domain;
+package org.apache.doris.stack.model.response;
 
-public class FeStartCommandRequestBody {
-    private String helpHostPort;
+import lombok.Data;
+import org.apache.doris.stack.constants.ExecutionStatus;
+import org.apache.doris.stack.constants.ProcessTypeEnum;
 
-    public String getHelpHostPort() {
-        return helpHostPort;
-    }
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.util.Date;
 
-    public void setHelpHostPort(String helpHostPort) {
-        this.helpHostPort = helpHostPort;
-    }
+/**
+ * current process resp
+ **/
+@Data
+public class CurrentProcessResp {
+
+    private int id;
+
+    private int clusterId;
+
+    private int processStep;
+
+    @Enumerated(EnumType.STRING)
+    private ProcessTypeEnum processType;
+
+    @Enumerated(EnumType.STRING)
+    private ExecutionStatus status;
+
+    private Date createTime;
+
+    private Date updateTime;
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/model/response/TaskInstanceResp.java b/manager/dm-server/src/main/java/org/apache/doris/stack/model/response/TaskInstanceResp.java
new file mode 100644
index 0000000..6f15c93
--- /dev/null
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/model/response/TaskInstanceResp.java
@@ -0,0 +1,64 @@
+// 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.doris.stack.model.response;
+
+import lombok.Data;
+import org.apache.doris.stack.constants.ExecutionStatus;
+import org.apache.doris.stack.constants.Flag;
+import org.apache.doris.stack.constants.ProcessTypeEnum;
+import org.apache.doris.stack.constants.TaskTypeEnum;
+
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import java.util.Date;
+
+/**
+ * task response
+ **/
+@Data
+public class TaskInstanceResp {
+
+    private int id;
+
+    private int processId;
+
+    private String host;
+
+    @Enumerated(EnumType.STRING)
+    private ProcessTypeEnum processType;
+
+    @Enumerated(EnumType.STRING)
+    private TaskTypeEnum taskType;
+
+    @Enumerated(EnumType.STRING)
+    private ExecutionStatus status;
+
+    private Date startTime;
+
+    private Date endTime;
+
+    @Enumerated(EnumType.ORDINAL)
+    private Flag finish;
+
+    @Enumerated(EnumType.ORDINAL)
+    private Flag skip;
+
+    private String taskRole;
+
+    private String response;
+}
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/runner/TaskExecuteThread.java b/manager/dm-server/src/main/java/org/apache/doris/stack/runner/TaskExecuteThread.java
index f35986e..645446d 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/runner/TaskExecuteThread.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/runner/TaskExecuteThread.java
@@ -25,7 +25,6 @@ import org.apache.doris.stack.dao.TaskInstanceRepository;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
 import org.apache.doris.stack.task.AbstractTask;
 import org.apache.doris.stack.task.InstallAgentTask;
-import org.apache.doris.stack.task.JoinBeTask;
 
 import java.util.concurrent.Callable;
 
@@ -69,8 +68,6 @@ public class TaskExecuteThread implements Callable<Object> {
         switch (taskType) {
             case INSTALL_AGENT:
                 return new InstallAgentTask(taskContext);
-            case JOIN_BE:
-                return new JoinBeTask(taskContext);
             default:
                 log.error("not support task type: {}", taskType.name());
                 throw new IllegalArgumentException("not support task type");
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/service/ProcessTask.java b/manager/dm-server/src/main/java/org/apache/doris/stack/service/ProcessTask.java
index 5016568..49ffac9 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/service/ProcessTask.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/service/ProcessTask.java
@@ -17,8 +17,9 @@
 
 package org.apache.doris.stack.service;
 
-import org.apache.doris.stack.entity.ProcessInstanceEntity;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
+import org.apache.doris.stack.model.response.CurrentProcessResp;
+import org.apache.doris.stack.model.response.TaskInstanceResp;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -30,11 +31,11 @@ public interface ProcessTask {
      * query user history installation progress
      * null means that nothing currently being installed
      */
-    ProcessInstanceEntity historyProgress(HttpServletRequest request, HttpServletResponse response) throws Exception;
+    CurrentProcessResp currentProcess(HttpServletRequest request, HttpServletResponse response) throws Exception;
 
     List<TaskInstanceEntity> processProgress(HttpServletRequest request, HttpServletResponse response, int processId);
 
-    List<TaskInstanceEntity> taskProgress(HttpServletRequest request, HttpServletResponse response, int processId);
+    List<TaskInstanceResp> taskProgress(HttpServletRequest request, HttpServletResponse response, int processId);
 
     void installComplete(HttpServletRequest request, HttpServletResponse response, int processId) throws Exception;
 
@@ -59,4 +60,5 @@ public interface ProcessTask {
      */
     Object taskLog(int taskId);
 
+    void backPrevious(int processId);
 }
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/AgentProcessImpl.java b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/AgentProcessImpl.java
index 0004794..bcd7997 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/AgentProcessImpl.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/AgentProcessImpl.java
@@ -25,7 +25,9 @@ import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.doris.manager.common.domain.AgentRoleRegister;
 import org.apache.doris.manager.common.domain.BeInstallCommandRequestBody;
+import org.apache.doris.manager.common.domain.BeStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.BrokerInstallCommandRequestBody;
+import org.apache.doris.manager.common.domain.BrokerStartCommandRequestBody;
 import org.apache.doris.manager.common.domain.CommandRequest;
 import org.apache.doris.manager.common.domain.CommandType;
 import org.apache.doris.manager.common.domain.FeInstallCommandRequestBody;
@@ -54,13 +56,13 @@ import org.apache.doris.stack.entity.AgentEntity;
 import org.apache.doris.stack.entity.AgentRoleEntity;
 import org.apache.doris.stack.entity.ProcessInstanceEntity;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
+import org.apache.doris.stack.exceptions.JdbcException;
 import org.apache.doris.stack.exceptions.ServerException;
 import org.apache.doris.stack.model.request.BeJoinReq;
 import org.apache.doris.stack.model.request.DeployConfigReq;
 import org.apache.doris.stack.model.request.DorisExecReq;
 import org.apache.doris.stack.model.request.DorisInstallReq;
 import org.apache.doris.stack.model.request.DorisStartReq;
-import org.apache.doris.stack.model.task.BeJoin;
 import org.apache.doris.stack.model.task.DeployConfig;
 import org.apache.doris.stack.model.task.DorisInstall;
 import org.apache.doris.stack.model.task.DorisStart;
@@ -78,6 +80,7 @@ import java.io.File;
 import java.io.UnsupportedEncodingException;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.sql.SQLSyntaxErrorException;
 import java.util.Base64;
 import java.util.List;
 import java.util.Properties;
@@ -121,7 +124,7 @@ public class AgentProcessImpl implements AgentProcess {
         int userId = authenticationService.checkAllUserAuthWithCookie(request, response);
         processInstanceComponent.checkProcessFinish(installReq.getProcessId());
         processInstanceComponent.checkHasUnfinishProcess(userId, installReq.getProcessId());
-        boolean success = taskInstanceComponent.checkParentTaskSuccess(installReq.getProcessId(), ProcessTypeEnum.INSTALL_SERVICE);
+        boolean success = taskInstanceComponent.checkTaskSuccess(installReq.getProcessId(), ProcessTypeEnum.INSTALL_AGENT);
         Preconditions.checkArgument(success, "The agent is not installed successfully and the service cannot be installed");
 
         ProcessInstanceEntity process = processInstanceComponent.refreshProcess(installReq.getProcessId(), ProcessTypeEnum.INSTALL_SERVICE);
@@ -133,6 +136,8 @@ public class AgentProcessImpl implements AgentProcess {
         if (installInfos == null) {
             throw new ServerException("Please specify the host configuration to be installed");
         }
+        //add broker
+        addBrokerInstallnfo(installInfos);
         for (DorisInstall install : installInfos) {
             String key = install.getHost() + "-" + install.getRole();
             if (agentRoleList.contains(key)) {
@@ -150,31 +155,48 @@ public class AgentProcessImpl implements AgentProcess {
         }
     }
 
+    /**
+     * auto install broker when install fe/be in install cluster
+     */
+    private void addBrokerInstallnfo(List<DorisInstall> installInfos) {
+        List<String> brokerList = installInfos.stream().map(DorisInstall::getHost).distinct().collect(Collectors.toList());
+        for (String broker : brokerList) {
+            DorisInstall brokerInstall = new DorisInstall();
+            brokerInstall.setHost(broker);
+            brokerInstall.setRole(ServiceRole.BROKER.name());
+            installInfos.add(brokerInstall);
+        }
+    }
+
     private void installDoris(int processId, DorisInstall install, String packageUrl, String installDir) {
         if (!installDir.endsWith(File.separator)) {
             installDir = installDir + File.separator;
         }
+        String serviceInstallDir = "";
         CommandRequest creq = new CommandRequest();
         TaskInstanceEntity installServiceTmp = new TaskInstanceEntity(processId, install.getHost(), ProcessTypeEnum.INSTALL_SERVICE, ExecutionStatus.SUBMITTED);
         if (ServiceRole.FE.name().equals(install.getRole())) {
+            serviceInstallDir = installDir + ServiceRole.FE.getInstallName();
             FeInstallCommandRequestBody feBody = new FeInstallCommandRequestBody();
             feBody.setMkFeMetadir(true);
             feBody.setPackageUrl(packageUrl);
-            feBody.setInstallDir(installDir + ServiceRole.FE.getInstallName());
+            feBody.setInstallDir(serviceInstallDir);
             creq.setCommandType(CommandType.INSTALL_FE.name());
             creq.setBody(JSON.toJSONString(feBody));
             installServiceTmp.setTaskType(TaskTypeEnum.INSTALL_FE);
         } else if (ServiceRole.BE.name().equals(install.getRole())) {
+            serviceInstallDir = installDir + ServiceRole.BE.getInstallName();
             BeInstallCommandRequestBody beBody = new BeInstallCommandRequestBody();
             beBody.setMkBeStorageDir(true);
             beBody.setPackageUrl(packageUrl);
-            beBody.setInstallDir(installDir + ServiceRole.BE.getInstallName());
+            beBody.setInstallDir(serviceInstallDir);
             creq.setCommandType(CommandType.INSTALL_BE.name());
             creq.setBody(JSON.toJSONString(beBody));
             installServiceTmp.setTaskType(TaskTypeEnum.INSTALL_BE);
         } else if (ServiceRole.BROKER.name().equals(install.getRole())) {
+            serviceInstallDir = installDir + ServiceRole.BROKER.getInstallName();
             BrokerInstallCommandRequestBody broker = new BrokerInstallCommandRequestBody();
-            broker.setInstallDir(installDir + ServiceRole.BROKER.getInstallName());
+            broker.setInstallDir(serviceInstallDir);
             broker.setPackageUrl(packageUrl);
             creq.setCommandType(CommandType.INSTALL_BROKER.name());
             creq.setBody(JSON.toJSONString(broker));
@@ -187,8 +209,8 @@ public class AgentProcessImpl implements AgentProcess {
             return;
         }
         handleAgentTask(installService, creq);
-        agentRoleComponent.saveAgentRole(new AgentRoleEntity(install.getHost(), install.getRole(), install.getFeNodeType(), installDir, Flag.NO));
-        log.info("agent {} installing doris {}", install.getHost(), install.getRole());
+        agentRoleComponent.saveAgentRole(new AgentRoleEntity(install.getHost(), install.getRole(), install.getFeNodeType(), serviceInstallDir, Flag.NO));
+        log.info("agent {} installing doris {} in dir {}", install.getHost(), install.getRole(), serviceInstallDir);
     }
 
     /**
@@ -216,7 +238,7 @@ public class AgentProcessImpl implements AgentProcess {
         int userId = authenticationService.checkAllUserAuthWithCookie(request, response);
         processInstanceComponent.checkProcessFinish(deployConfigReq.getProcessId());
         processInstanceComponent.checkHasUnfinishProcess(userId, deployConfigReq.getProcessId());
-        boolean success = taskInstanceComponent.checkParentTaskSuccess(deployConfigReq.getProcessId(), ProcessTypeEnum.DEPLOY_CONFIG);
+        boolean success = taskInstanceComponent.checkTaskSuccess(deployConfigReq.getProcessId(), ProcessTypeEnum.INSTALL_SERVICE);
         Preconditions.checkArgument(success, "doris is not installed successfully and the configuration cannot be delivered");
 
         ProcessInstanceEntity process = processInstanceComponent.refreshProcess(deployConfigReq.getProcessId(), ProcessTypeEnum.DEPLOY_CONFIG);
@@ -292,11 +314,12 @@ public class AgentProcessImpl implements AgentProcess {
         int userId = authenticationService.checkAllUserAuthWithCookie(request, response);
         processInstanceComponent.checkProcessFinish(dorisStart.getProcessId());
         processInstanceComponent.checkHasUnfinishProcess(userId, dorisStart.getProcessId());
-        boolean success = taskInstanceComponent.checkParentTaskSuccess(dorisStart.getProcessId(), ProcessTypeEnum.START_SERVICE);
+        boolean success = taskInstanceComponent.checkTaskSuccess(dorisStart.getProcessId(), ProcessTypeEnum.DEPLOY_CONFIG);
         Preconditions.checkArgument(success, "The configuration was not successfully delivered and the service could not be started");
 
         ProcessInstanceEntity process = processInstanceComponent.refreshProcess(dorisStart.getProcessId(), ProcessTypeEnum.START_SERVICE);
         List<DorisStart> dorisStarts = dorisStart.getDorisStarts();
+        addBrokerStart(dorisStarts);
         for (DorisStart start : dorisStarts) {
             TaskInstanceEntity execTaskTmp = new TaskInstanceEntity(process.getId(), start.getHost(), ProcessTypeEnum.START_SERVICE, ExecutionStatus.SUBMITTED);
             TaskTypeEnum parentTask;
@@ -380,6 +403,19 @@ public class AgentProcessImpl implements AgentProcess {
         }
     }
 
+    /**
+     * auto start broker when start fe/be in install cluster
+     */
+    private void addBrokerStart(List<DorisStart> dorisStarts) {
+        List<String> brokerList = dorisStarts.stream().map(DorisStart::getHost).distinct().collect(Collectors.toList());
+        for (String broker : brokerList) {
+            DorisStart brokerStart = new DorisStart();
+            brokerStart.setHost(broker);
+            brokerStart.setRole(ServiceRole.BROKER.name());
+            dorisStarts.add(brokerStart);
+        }
+    }
+
     private String waitMasterFeStart(int processId) throws InterruptedException {
         String masterFeHost;
         while (true) {
@@ -410,10 +446,18 @@ public class AgentProcessImpl implements AgentProcess {
                     Integer leaderFeEditLogPort = getFeEditLogPort(leaderFeHost, agentCache.agentPort(leaderFeHost));
                     feBody.setHelpHostPort(leaderFeHost + ":" + leaderFeEditLogPort);
                 }
+                feBody.setStopBeforeStart(true);
                 creq.setBody(JSON.toJSONString(feBody));
                 break;
             case START_BE:
+                BeStartCommandRequestBody beBody = new BeStartCommandRequestBody();
+                beBody.setStopBeforeStart(true);
+                creq.setBody(JSON.toJSONString(beBody));
+                break;
             case START_BROKER:
+                BrokerStartCommandRequestBody brokerBody = new BrokerStartCommandRequestBody();
+                brokerBody.setStopBeforeStart(true);
+                creq.setBody(JSON.toJSONString(brokerBody));
                 break;
             default:
                 log.error("not support command: {}", commandType.name());
@@ -532,30 +576,45 @@ public class AgentProcessImpl implements AgentProcess {
 
     @Override
     public void joinBe(HttpServletRequest request, HttpServletResponse response, BeJoinReq beJoinReq) throws Exception {
+        Preconditions.checkArgument(ObjectUtils.isNotEmpty(beJoinReq.getHosts()), "not find backends");
         int userId = authenticationService.checkAllUserAuthWithCookie(request, response);
         processInstanceComponent.checkProcessFinish(beJoinReq.getProcessId());
         processInstanceComponent.checkHasUnfinishProcess(userId, beJoinReq.getProcessId());
-        boolean success = taskInstanceComponent.checkParentTaskSuccess(beJoinReq.getProcessId(), ProcessTypeEnum.BUILD_CLUSTER);
+        boolean success = taskInstanceComponent.checkTaskSuccess(beJoinReq.getProcessId(), ProcessTypeEnum.START_SERVICE);
         Preconditions.checkArgument(success, "The service has not been started and completed, and the component cannot be clustered");
-        ProcessInstanceEntity process = processInstanceComponent.refreshProcess(beJoinReq.getProcessId(), ProcessTypeEnum.BUILD_CLUSTER);
 
+        ProcessInstanceEntity process = processInstanceComponent.queryProcessById(beJoinReq.getProcessId());
         //Query the alive agent that installed fe and get fe's query port
         AgentEntity aliveAgent = getAliveAgent(process.getClusterId());
         Integer queryPort = getFeQueryPort(aliveAgent.getHost(), aliveAgent.getPort());
+        Connection conn = null;
+        try {
+            conn = JdbcUtil.getConnection(aliveAgent.getHost(), queryPort);
+        } catch (SQLException e) {
+            log.error("get connection fail, host {}, port {} :", aliveAgent.getHost(), queryPort, e);
+            throw new JdbcException("Failed to get fe's jdbc connection");
+        }
+
+        StringBuilder joinBeSb = new StringBuilder();
         for (String be : beJoinReq.getHosts()) {
-            boolean parentTaskSkip = checkParentTaskSkip(beJoinReq.getProcessId(), be, TaskTypeEnum.START_BE);
-            if (parentTaskSkip) {
-                log.warn("host {} parent start be task has skipped,so the current add be to cluster task is also skipped", be);
-                continue;
-            }
-            TaskInstanceEntity joinBeTask = taskInstanceComponent.saveTask(process.getId(), be, ProcessTypeEnum.BUILD_CLUSTER, TaskTypeEnum.JOIN_BE, ExecutionStatus.SUBMITTED);
-            if (joinBeTask == null) {
+            Properties beConf = agentRest.roleConfig(be, agentCache.agentPort(be), ServiceRole.BE.name());
+            String beHeatPort = beConf.getProperty(Constants.KEY_BE_HEARTBEAT_PORT);
+            joinBeSb.append("\"").append(be).append(":").append(beHeatPort).append("\"").append(",");
+        }
+        String joinBeStr = joinBeSb.deleteCharAt(joinBeSb.length() - 1).toString();
+        String addBe = String.format("ALTER SYSTEM ADD BACKEND %s", joinBeStr);
+        try {
+            log.info("execute {}", addBe);
+            JdbcUtil.execute(conn, addBe);
+        } catch (SQLException e) {
+            if (e instanceof SQLSyntaxErrorException
+                    && StringUtils.isNotBlank(e.getMessage())
+                    && e.getMessage().contains(Constants.BE_EXIST_MSG)) {
+                log.info("backend already exist,response:{}", e.getMessage());
                 return;
             }
-            int agentPort = agentCache.agentPort(be);
-            BeJoin beJoin = new BeJoin(aliveAgent.getHost(), queryPort, be, agentPort);
-            joinBeTask.setTaskJson(JSON.toJSONString(beJoin));
-            taskExecuteRunner.execTask(joinBeTask, beJoin);
+            log.error("Failed to add backend:{}", joinBeStr, e);
+            throw new ServerException(e.getMessage());
         }
     }
 
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ProcessTaskImpl.java b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ProcessTaskImpl.java
index fec9ce9..5139ac0 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ProcessTaskImpl.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ProcessTaskImpl.java
@@ -31,12 +31,15 @@ import org.apache.doris.stack.component.ProcessInstanceComponent;
 import org.apache.doris.stack.component.TaskInstanceComponent;
 import org.apache.doris.stack.constants.ExecutionStatus;
 import org.apache.doris.stack.constants.Flag;
+import org.apache.doris.stack.constants.ProcessTypeEnum;
 import org.apache.doris.stack.constants.TaskTypeEnum;
 import org.apache.doris.stack.dao.TaskInstanceRepository;
 import org.apache.doris.stack.entity.AgentEntity;
 import org.apache.doris.stack.entity.ProcessInstanceEntity;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
 import org.apache.doris.stack.exceptions.ServerException;
+import org.apache.doris.stack.model.response.CurrentProcessResp;
+import org.apache.doris.stack.model.response.TaskInstanceResp;
 import org.apache.doris.stack.model.task.AgentInstall;
 import org.apache.doris.stack.model.task.BeJoin;
 import org.apache.doris.stack.runner.TaskExecuteRunner;
@@ -44,6 +47,7 @@ import org.apache.doris.stack.service.ProcessTask;
 import org.apache.doris.stack.service.user.AuthenticationService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -79,10 +83,25 @@ public class ProcessTaskImpl implements ProcessTask {
     private TaskExecuteRunner taskExecuteRunner;
 
     @Override
-    public ProcessInstanceEntity historyProgress(HttpServletRequest request, HttpServletResponse response) throws Exception {
+    public CurrentProcessResp currentProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {
         int userId = authenticationService.checkAllUserAuthWithCookie(request, response);
         ProcessInstanceEntity processEntity = processInstanceComponent.queryProcessByuserId(userId);
-        return processEntity;
+        CurrentProcessResp processResp = null;
+        if (processEntity != null) {
+            List<TaskInstanceEntity> taskEntities = taskInstanceRepository.queryTasksByProcessStep(processEntity.getId(), processEntity.getProcessType());
+            boolean hasUnFinishTask = false;
+            for (TaskInstanceEntity task : taskEntities) {
+                if (!task.getFinish().typeIsYes()) {
+                    hasUnFinishTask = true;
+                    break;
+                }
+            }
+            processResp = processEntity.transToCurrentResp();
+            if (!hasUnFinishTask && !processEntity.getProcessType().endProcess()) {
+                processResp.setProcessStep(processResp.getProcessStep() + 1);
+            }
+        }
+        return processResp;
     }
 
     @Override
@@ -98,28 +117,29 @@ public class ProcessTaskImpl implements ProcessTask {
     }
 
     @Override
-    public List<TaskInstanceEntity> taskProgress(HttpServletRequest request, HttpServletResponse response, int processId) {
+    public List<TaskInstanceResp> taskProgress(HttpServletRequest request, HttpServletResponse response, int processId) {
         ProcessInstanceEntity processEntity = processInstanceComponent.queryProcessById(processId);
         Preconditions.checkArgument(processEntity != null, "can not find processId " + processId);
         refreshAgentTaskStatus(processId);
         List<TaskInstanceEntity> taskEntities = taskInstanceRepository.queryTasksByProcessStep(processId, processEntity.getProcessType());
-        List<TaskInstanceEntity> resultTasks = Lists.newArrayList();
+        List<TaskInstanceResp> resultTasks = Lists.newArrayList();
         for (TaskInstanceEntity task : taskEntities) {
             if (task.getSkip().typeIsYes()) {
                 continue;
             }
+            TaskInstanceResp taskResp = task.transToModel();
             //set response
             if (task.getStatus().typeIsSuccess()) {
-                task.setResponse(task.getTaskType().getName() + " success");
+                taskResp.setResponse(task.getTaskType().getName() + " success");
             } else if (task.getStatus().typeIsFailure()) {
                 if (StringUtils.isBlank(task.getResult())) {
-                    task.setResponse(task.getTaskType().getName() + " fail");
+                    taskResp.setResponse(task.getTaskType().getName() + " fail");
                 } else {
-                    task.setResponse(task.getResult());
+                    taskResp.setResponse(task.getResult());
                 }
             }
-            task.setTaskRole(task.getTaskType().parseTaskRole());
-            resultTasks.add(task);
+            taskResp.setTaskRole(task.getTaskType().parseTaskRole());
+            resultTasks.add(taskResp);
         }
         return resultTasks;
     }
@@ -225,6 +245,23 @@ public class ProcessTaskImpl implements ProcessTask {
         }
     }
 
+    @Transactional
+    @Override
+    public void backPrevious(int processId) {
+        ProcessInstanceEntity processEntity = processInstanceComponent.queryProcessById(processId);
+        Preconditions.checkNotNull(processEntity, "process not exist");
+        ProcessTypeEnum processType = processEntity.getProcessType();
+        Preconditions.checkArgument(processType == ProcessTypeEnum.START_SERVICE, "process can not back");
+
+        //remove history task
+        List<TaskInstanceEntity> startServiceTasks = taskInstanceRepository.queryTasksByProcessStep(processEntity.getId(), ProcessTypeEnum.START_SERVICE);
+        taskInstanceRepository.deleteAll(startServiceTasks);
+
+        ProcessTypeEnum parent = ProcessTypeEnum.findParent(processType);
+        processEntity.setProcessType(parent);
+        processInstanceComponent.saveProcess(processEntity);
+    }
+
     private int agentPort(String host) {
         AgentEntity agent = agentCache.agentInfo(host);
         if (agent == null) {
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ServerProcessImpl.java b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ServerProcessImpl.java
index 29cd8ff..eccfbf4 100644
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ServerProcessImpl.java
+++ b/manager/dm-server/src/main/java/org/apache/doris/stack/service/impl/ServerProcessImpl.java
@@ -35,7 +35,6 @@ import org.apache.doris.stack.entity.AgentEntity;
 import org.apache.doris.stack.entity.AgentRoleEntity;
 import org.apache.doris.stack.entity.ProcessInstanceEntity;
 import org.apache.doris.stack.entity.TaskInstanceEntity;
-import org.apache.doris.stack.exceptions.ServerException;
 import org.apache.doris.stack.model.request.AgentInstallReq;
 import org.apache.doris.stack.model.request.AgentRegister;
 import org.apache.doris.stack.model.task.AgentInstall;
@@ -50,6 +49,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -110,11 +110,16 @@ public class ServerProcessImpl implements ServerProcess {
         return processId;
     }
 
+    /**
+     * remove already install agent host
+     */
     private void checkAgentInstall(AgentInstallReq installReq) {
-        for (String host : installReq.getHosts()) {
+        Iterator<String> iterator = installReq.getHosts().iterator();
+        while (iterator.hasNext()) {
+            String host = iterator.next();
             if (agentCache.containsAgent(host)) {
-                log.error("host {} already install agent", host);
-                throw new ServerException("host " + host + " already install agent");
+                log.warn("host {} already install agent,skipped", host);
+                iterator.remove();
             }
         }
     }
@@ -138,6 +143,7 @@ public class ServerProcessImpl implements ServerProcess {
     @Override
     public List<AgentEntity> agentList(int clusterId) {
         List<AgentEntity> agentEntities = agentComponent.queryAgentNodes(clusterId);
+        agentCache.refresh(agentEntities);
         return agentEntities;
     }
 
diff --git a/manager/dm-server/src/main/java/org/apache/doris/stack/task/JoinBeTask.java b/manager/dm-server/src/main/java/org/apache/doris/stack/task/JoinBeTask.java
deleted file mode 100644
index 0069d40..0000000
--- a/manager/dm-server/src/main/java/org/apache/doris/stack/task/JoinBeTask.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.doris.stack.task;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.doris.manager.common.domain.ServiceRole;
-import org.apache.doris.stack.agent.AgentRest;
-import org.apache.doris.stack.bean.SpringApplicationContext;
-import org.apache.doris.stack.constants.Constants;
-import org.apache.doris.stack.exceptions.JdbcException;
-import org.apache.doris.stack.exceptions.ServerException;
-import org.apache.doris.stack.model.task.BeJoin;
-import org.apache.doris.stack.runner.TaskContext;
-import org.apache.doris.stack.util.JdbcUtil;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLSyntaxErrorException;
-import java.util.Properties;
-
-/**
- * join be to cluster
- **/
-@Slf4j
-public class JoinBeTask extends AbstractTask {
-
-    private final String BE_EXIST_MSG = "Same backend already exists";
-    private AgentRest agentRest;
-
-    public JoinBeTask(TaskContext taskContext) {
-        super(taskContext);
-        this.agentRest = SpringApplicationContext.getBean(AgentRest.class);
-    }
-
-    @Override
-    public Object handle() {
-        BeJoin taskDesc = (BeJoin) taskContext.getTaskDesc();
-        String backendHost = taskDesc.getBeHost();
-        Properties beConf = agentRest.roleConfig(backendHost, taskDesc.getAgentPort(), ServiceRole.BE.name());
-        String beHeatPort = beConf.getProperty(Constants.KEY_BE_HEARTBEAT_PORT);
-        Connection conn = null;
-        try {
-            conn = JdbcUtil.getConnection(taskDesc.getFeHost(), taskDesc.getFeQueryPort());
-        } catch (SQLException e) {
-            log.error("get connection fail:", e);
-            throw new JdbcException("Failed to get fe's jdbc connection");
-        }
-
-        String addBeSqlFormat = "ALTER SYSTEM ADD BACKEND \"%s:%s\"";
-        String addBe = String.format(addBeSqlFormat, taskDesc.getBeHost(), beHeatPort);
-        try {
-            JdbcUtil.execute(conn, addBe);
-            return "Add backend success";
-        } catch (SQLException e) {
-            if (e instanceof SQLSyntaxErrorException
-                    && StringUtils.isNotBlank(e.getMessage())
-                    && e.getMessage().contains(BE_EXIST_MSG)) {
-                log.info("backend already add,response:{}", e.getMessage());
-                return "Backend already exist";
-            }
-            log.error("Failed to add backend:{}:{}", taskDesc.getBeHost(), beHeatPort, e);
-            throw new ServerException(e.getMessage());
-        }
-    }
-}
diff --git "a/manager/doc/Doris Manager Server \346\216\245\345\217\243\346\226\207\346\241\243.md" "b/manager/doc/Doris Manager Server \346\216\245\345\217\243\346\226\207\346\241\243.md"
index 898826f..c8e62b3 100644
--- "a/manager/doc/Doris Manager Server \346\216\245\345\217\243\346\226\207\346\241\243.md"	
+++ "b/manager/doc/Doris Manager Server \346\216\245\345\217\243\346\226\207\346\241\243.md"	
@@ -421,7 +421,7 @@
 
 **URL**
 
-> /api/process/historyProgress
+> /api/process/currentProcess
 
 **支持格式**
 
@@ -439,13 +439,17 @@
 > |:-----   |:------|:-----------------------------   |
 > |msg   |String    |调用信息   |
 > |code  |String | 结果状态。0:正常  |
-> |data.id  |String | 流程id |
-> |data.processType   |String | 流程进度  |
+> |data.id  |String | 当前安装流程id |
+> |data.processType   |String | 当前安装流程类型(进度):INSTALL_AGENT 安装Agent,INSTALL_SERVICE 安装服务,DEPLOY_CONFIG 分发配置,START_SERVICE 启动服务,BUILD_CLUSTER 组件集群  |
+> |data.processStep   |int | 流程步骤:0,1,2,3  |
 > |data.finish   |String | 流程完成标志  |
+> |data.status   |String | 流程状态  |
+> |data.createTime   |Date | 创建时间  |
+> |data.updateTime   |Date | 更新时间  |
 
 **接口示例**
 
-> 地址:http://localhost:9601/api/process/historyProgress
+> 地址:http://localhost:9601/api/process/currentProcess
 
 > 返回参数:
 ``` json
@@ -455,8 +459,8 @@
     "data": {
         "id": 1,
         "clusterId": 0,
-        "userId": 0,
         "processType": "START_SERVICE",
+        "processStep": 0,
         "createTime": "2021-11-02T01:29:58.000+00:00",
         "updateTime": "2021-11-02T01:29:58.000+00:00",
         "finish": "NO"
@@ -873,4 +877,47 @@
         "host": "127.0.0.1"
     }]
 }
+```
+
+
+#### 16.返回上一步
+
+**接口功能**
+
+> 返回上一步,只有第四步可以返回上一步,其余均不可返回上一步
+
+**URL**
+
+> /api/process/back/{processId}
+
+**支持格式**
+
+> JSON
+
+**HTTP请求方式**
+
+> POST
+
+**请求参数**
+无
+
+**返回字段**
+
+> |返回字段|字段类型|说明                              |
+> |:-----   |:------|:-----------------------------   |
+> |msg   |String    |调用信息   |
+> |code  |String | 结果状态。0:正常  |
+
+**接口示例**
+
+> 地址:http://localhost:9601/api/process/back/1
+
+> 请求参数:无
+
+> 返回参数:
+``` json
+{
+    "msg": "success",
+    "code": 0
+}
 ```
\ No newline at end of file

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org