This is an automated email from the ASF dual-hosted git repository.
wuzhiguo 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 16fa4fd0 BIGTOP-4315: Support cluster start/stop/restart commands
(#138)
16fa4fd0 is described below
commit 16fa4fd0bba82f1c353f52baf01cc2bf1dfc01bc
Author: Zhiguo Wu <[email protected]>
AuthorDate: Fri Jan 3 15:19:43 2025 +0800
BIGTOP-4315: Support cluster start/stop/restart commands (#138)
---
.../bigtop/manager/common/enums/Command.java | 13 +-
.../factory/cluster/ClusterRestartJobFactory.java | 48 +++++++
.../factory/cluster/ClusterStartJobFactory.java | 48 +++++++
.../factory/cluster/ClusterStopJobFactory.java | 48 +++++++
.../server/command/job/AbstractClusterJob.java | 139 +++++++++++++++++++++
.../server/command/job/AbstractServiceJob.java | 46 ++-----
.../server/command/job/ClusterRestartJob.java | 38 ++++++
.../server/command/job/ClusterStartJob.java | 36 ++++++
.../manager/server/command/job/ClusterStopJob.java | 36 ++++++
.../manager/server/enums/ApiExceptionEnum.java | 2 +-
.../manager/server/model/dto/CommandDTO.java | 16 ---
.../manager/server/model/req/CommandReq.java | 8 +-
.../bigtop/manager/server/utils/StackDAGUtils.java | 65 ++++++++++
.../bigtop/manager/server/utils/StackUtils.java | 11 ++
14 files changed, 485 insertions(+), 69 deletions(-)
diff --git
a/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/enums/Command.java
b/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/enums/Command.java
index 4af14bc5..6f9457af 100644
---
a/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/enums/Command.java
+++
b/bigtop-manager-common/src/main/java/org/apache/bigtop/manager/common/enums/Command.java
@@ -28,23 +28,18 @@ import lombok.Getter;
@AllArgsConstructor
@Getter
public enum Command {
+ // Available for: Cluster, Host, Service, Component
ADD("add", "Add"),
-
REMOVE("remove", "Remove"),
-
START("start", "Start"),
-
STOP("stop", "Stop"),
-
- STATUS("status", "Status"),
-
RESTART("restart", "Restart"),
- CONFIGURE("configure", "Configure"),
-
+ // Available for: Service, Component
+ STATUS("status", "Status"),
CHECK("check", "Check"),
-
CUSTOM("custom", "Custom"),
+ CONFIGURE("configure", "Configure"),
;
private final String code;
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterRestartJobFactory.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterRestartJobFactory.java
new file mode 100644
index 00000000..9ad6a2c3
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterRestartJobFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.factory.cluster;
+
+import org.apache.bigtop.manager.common.enums.Command;
+import org.apache.bigtop.manager.server.command.CommandIdentifier;
+import org.apache.bigtop.manager.server.command.job.ClusterRestartJob;
+import org.apache.bigtop.manager.server.command.job.Job;
+import org.apache.bigtop.manager.server.command.job.JobContext;
+import org.apache.bigtop.manager.server.enums.CommandLevel;
+
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ClusterRestartJobFactory extends AbstractClusterJobFactory {
+
+ @Override
+ public CommandIdentifier getCommandIdentifier() {
+ return new CommandIdentifier(CommandLevel.CLUSTER, Command.RESTART);
+ }
+
+ @Override
+ public Job createJob(JobContext jobContext) {
+ return new ClusterRestartJob(jobContext);
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStartJobFactory.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStartJobFactory.java
new file mode 100644
index 00000000..b1b33515
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStartJobFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.factory.cluster;
+
+import org.apache.bigtop.manager.common.enums.Command;
+import org.apache.bigtop.manager.server.command.CommandIdentifier;
+import org.apache.bigtop.manager.server.command.job.ClusterStartJob;
+import org.apache.bigtop.manager.server.command.job.Job;
+import org.apache.bigtop.manager.server.command.job.JobContext;
+import org.apache.bigtop.manager.server.enums.CommandLevel;
+
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ClusterStartJobFactory extends AbstractClusterJobFactory {
+
+ @Override
+ public CommandIdentifier getCommandIdentifier() {
+ return new CommandIdentifier(CommandLevel.CLUSTER, Command.START);
+ }
+
+ @Override
+ public Job createJob(JobContext jobContext) {
+ return new ClusterStartJob(jobContext);
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStopJobFactory.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStopJobFactory.java
new file mode 100644
index 00000000..9290040b
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/factory/cluster/ClusterStopJobFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.factory.cluster;
+
+import org.apache.bigtop.manager.common.enums.Command;
+import org.apache.bigtop.manager.server.command.CommandIdentifier;
+import org.apache.bigtop.manager.server.command.job.ClusterStopJob;
+import org.apache.bigtop.manager.server.command.job.Job;
+import org.apache.bigtop.manager.server.command.job.JobContext;
+import org.apache.bigtop.manager.server.enums.CommandLevel;
+
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ClusterStopJobFactory extends AbstractClusterJobFactory {
+
+ @Override
+ public CommandIdentifier getCommandIdentifier() {
+ return new CommandIdentifier(CommandLevel.CLUSTER, Command.STOP);
+ }
+
+ @Override
+ public Job createJob(JobContext jobContext) {
+ return new ClusterStopJob(jobContext);
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractClusterJob.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractClusterJob.java
new file mode 100644
index 00000000..4787e197
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractClusterJob.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.job;
+
+import org.apache.bigtop.manager.common.enums.Command;
+import org.apache.bigtop.manager.dao.po.ComponentPO;
+import org.apache.bigtop.manager.dao.query.ComponentQuery;
+import org.apache.bigtop.manager.dao.repository.ComponentDao;
+import org.apache.bigtop.manager.server.command.stage.ComponentStartStage;
+import org.apache.bigtop.manager.server.command.stage.ComponentStopStage;
+import org.apache.bigtop.manager.server.command.stage.StageContext;
+import org.apache.bigtop.manager.server.holder.SpringContextHolder;
+import org.apache.bigtop.manager.server.model.dto.ComponentDTO;
+import org.apache.bigtop.manager.server.model.dto.ServiceDTO;
+import org.apache.bigtop.manager.server.utils.StackDAGUtils;
+import org.apache.bigtop.manager.server.utils.StackUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractClusterJob extends AbstractJob {
+
+ protected ComponentDao componentDao;
+
+ public AbstractClusterJob(JobContext jobContext) {
+ super(jobContext);
+ }
+
+ @Override
+ protected void injectBeans() {
+ super.injectBeans();
+
+ this.componentDao = SpringContextHolder.getBean(ComponentDao.class);
+ }
+
+ @Override
+ protected void beforeCreateStages() {
+ super.beforeCreateStages();
+ }
+
+ protected StageContext createStageContext(String componentName,
List<String> hostnames) {
+ StageContext stageContext =
StageContext.fromCommandDTO(jobContext.getCommandDTO());
+
+ ServiceDTO serviceDTO =
StackUtils.getServiceDTOByComponentName(componentName);
+ ComponentDTO componentDTO = StackUtils.getComponentDTO(componentName);
+
+ stageContext.setHostnames(hostnames);
+ stageContext.setServiceDTO(serviceDTO);
+ stageContext.setComponentDTO(componentDTO);
+
+ return stageContext;
+ }
+
+ protected void createStartStages() {
+ List<ComponentPO> componentPOList = getComponentPOList();
+ List<String> todoList =
StackDAGUtils.getTodoList(getComponentNames(componentPOList), Command.START);
+
+ for (String componentCommand : todoList) {
+ String[] split = componentCommand.split("-");
+ String componentName = split[0];
+
+ if (StackUtils.isClientComponent(componentName)) {
+ continue;
+ }
+
+ List<String> hostnames =
findHostnamesByComponentName(componentPOList, componentName);
+ if (CollectionUtils.isEmpty(hostnames)) {
+ continue;
+ }
+
+ StageContext stageContext = createStageContext(componentName,
hostnames);
+ stages.add(new ComponentStartStage(stageContext));
+ }
+ }
+
+ protected void createStopStages() {
+ List<ComponentPO> componentPOList = getComponentPOList();
+ List<String> todoList =
StackDAGUtils.getTodoList(getComponentNames(componentPOList), Command.STOP);
+
+ for (String componentCommand : todoList) {
+ String[] split = componentCommand.split("-");
+ String componentName = split[0];
+
+ if (StackUtils.isClientComponent(componentName)) {
+ continue;
+ }
+
+ List<String> hostnames =
findHostnamesByComponentName(componentPOList, componentName);
+ if (CollectionUtils.isEmpty(hostnames)) {
+ continue;
+ }
+
+ StageContext stageContext = createStageContext(componentName,
hostnames);
+ stages.add(new ComponentStopStage(stageContext));
+ }
+ }
+
+ private List<ComponentPO> getComponentPOList() {
+ return componentDao.findByQuery(
+ ComponentQuery.builder().clusterId(clusterPO.getId()).build());
+ }
+
+ private List<String> getComponentNames(List<ComponentPO> componentPOList) {
+ if (componentPOList == null) {
+ return new ArrayList<>();
+ } else {
+ return
componentPOList.stream().map(ComponentPO::getName).distinct().toList();
+ }
+ }
+
+ private List<String> findHostnamesByComponentName(List<ComponentPO>
componentPOList, String componentName) {
+ if (componentPOList == null) {
+ return new ArrayList<>();
+ } else {
+ return componentPOList.stream()
+ .filter(componentPO ->
componentPO.getName().equals(componentName))
+ .map(ComponentPO::getHostname)
+ .toList();
+ }
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractServiceJob.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractServiceJob.java
index 8f128f1a..653e55ba 100644
---
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractServiceJob.java
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/AbstractServiceJob.java
@@ -18,7 +18,6 @@
*/
package org.apache.bigtop.manager.server.command.job;
-import org.apache.bigtop.manager.common.constants.ComponentCategories;
import org.apache.bigtop.manager.common.enums.Command;
import org.apache.bigtop.manager.dao.po.ComponentPO;
import org.apache.bigtop.manager.dao.query.ComponentQuery;
@@ -34,12 +33,12 @@ import
org.apache.bigtop.manager.server.command.stage.ComponentConfigureStage;
import org.apache.bigtop.manager.server.command.stage.ComponentStartStage;
import org.apache.bigtop.manager.server.command.stage.ComponentStopStage;
import org.apache.bigtop.manager.server.command.stage.StageContext;
-import org.apache.bigtop.manager.server.exception.ServerException;
import org.apache.bigtop.manager.server.holder.SpringContextHolder;
import org.apache.bigtop.manager.server.model.dto.ComponentDTO;
import org.apache.bigtop.manager.server.model.dto.ComponentHostDTO;
import org.apache.bigtop.manager.server.model.dto.ServiceDTO;
import org.apache.bigtop.manager.server.model.dto.command.ServiceCommandDTO;
+import org.apache.bigtop.manager.server.utils.StackDAGUtils;
import org.apache.bigtop.manager.server.utils.StackUtils;
import org.apache.commons.collections4.CollectionUtils;
@@ -88,25 +87,6 @@ public abstract class AbstractServiceJob extends AbstractJob
{
return stageContext;
}
- protected List<String> getTodoListForCommand(Command command) {
- try {
- List<String> orderedList =
- StackUtils.DAG.getAllNodesList().isEmpty() ? new
ArrayList<>() : StackUtils.DAG.topologicalSort();
- List<String> componentNames = getComponentNames();
- List<String> componentCommandNames = new
ArrayList<>(componentNames.stream()
- .map(x -> x + "-" + command.name().toUpperCase())
- .toList());
-
- orderedList.retainAll(componentCommandNames);
- componentCommandNames.removeAll(orderedList);
- orderedList.addAll(componentCommandNames);
-
- return orderedList;
- } catch (Exception e) {
- throw new ServerException(e);
- }
- }
-
protected List<String> getComponentNames() {
List<String> serviceNames = getServiceNames();
ComponentQuery componentQuery = ComponentQuery.builder()
@@ -122,16 +102,6 @@ public abstract class AbstractServiceJob extends
AbstractJob {
return
StackUtils.getServiceDTOByComponentName(componentName).getName();
}
- protected Boolean isServerComponent(String componentName) {
- ComponentDTO componentDTO = StackUtils.getComponentDTO(componentName);
- return
componentDTO.getCategory().equalsIgnoreCase(ComponentCategories.SERVER);
- }
-
- protected Boolean isClientComponent(String componentName) {
- ComponentDTO componentDTO = StackUtils.getComponentDTO(componentName);
- return
componentDTO.getCategory().equalsIgnoreCase(ComponentCategories.CLIENT);
- }
-
protected List<String> findHostnamesByComponentName(String componentName) {
ComponentQuery componentQuery = ComponentQuery.builder()
.clusterId(clusterPO.getId())
@@ -151,7 +121,7 @@ public abstract class AbstractServiceJob extends
AbstractJob {
}
protected void createAddStages() {
- List<String> todoList = getTodoListForCommand(Command.ADD);
+ List<String> todoList = StackDAGUtils.getTodoList(getComponentNames(),
Command.ADD);
for (String componentCommand : todoList) {
String[] split = componentCommand.split("-");
@@ -181,14 +151,14 @@ public abstract class AbstractServiceJob extends
AbstractJob {
}
protected void createStartStages() {
- List<String> todoList = getTodoListForCommand(Command.START);
+ List<String> todoList = StackDAGUtils.getTodoList(getComponentNames(),
Command.START);
for (String componentCommand : todoList) {
String[] split = componentCommand.split("-");
String componentName = split[0];
String serviceName = findServiceNameByComponentName(componentName);
- if (isClientComponent(componentName)) {
+ if (StackUtils.isClientComponent(componentName)) {
continue;
}
@@ -203,14 +173,14 @@ public abstract class AbstractServiceJob extends
AbstractJob {
}
protected void createStopStages() {
- List<String> todoList = getTodoListForCommand(Command.STOP);
+ List<String> todoList = StackDAGUtils.getTodoList(getComponentNames(),
Command.STOP);
for (String componentCommand : todoList) {
String[] split = componentCommand.split("-");
String componentName = split[0];
String serviceName = findServiceNameByComponentName(componentName);
- if (isClientComponent(componentName)) {
+ if (StackUtils.isClientComponent(componentName)) {
continue;
}
@@ -225,14 +195,14 @@ public abstract class AbstractServiceJob extends
AbstractJob {
}
protected void createCheckStages() {
- List<String> todoList = getTodoListForCommand(Command.CHECK);
+ List<String> todoList = StackDAGUtils.getTodoList(getComponentNames(),
Command.CHECK);
for (String componentCommand : todoList) {
String[] split = componentCommand.split("-");
String componentName = split[0];
String serviceName = findServiceNameByComponentName(componentName);
- if (isClientComponent(componentName)) {
+ if (StackUtils.isClientComponent(componentName)) {
continue;
}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterRestartJob.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterRestartJob.java
new file mode 100644
index 00000000..53d02c9a
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterRestartJob.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.job;
+
+public class ClusterRestartJob extends AbstractClusterJob {
+
+ public ClusterRestartJob(JobContext jobContext) {
+ super(jobContext);
+ }
+
+ @Override
+ protected void createStages() {
+ super.createStopStages();
+
+ super.createStartStages();
+ }
+
+ @Override
+ public String getName() {
+ return "Restart cluster";
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStartJob.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStartJob.java
new file mode 100644
index 00000000..39036df2
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStartJob.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.job;
+
+public class ClusterStartJob extends AbstractClusterJob {
+
+ public ClusterStartJob(JobContext jobContext) {
+ super(jobContext);
+ }
+
+ @Override
+ protected void createStages() {
+ super.createStartStages();
+ }
+
+ @Override
+ public String getName() {
+ return "Start cluster";
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStopJob.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStopJob.java
new file mode 100644
index 00000000..843d7a50
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/command/job/ClusterStopJob.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.command.job;
+
+public class ClusterStopJob extends AbstractClusterJob {
+
+ public ClusterStopJob(JobContext jobContext) {
+ super(jobContext);
+ }
+
+ @Override
+ protected void createStages() {
+ super.createStopStages();
+ }
+
+ @Override
+ public String getName() {
+ return "Stop cluster";
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/enums/ApiExceptionEnum.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/enums/ApiExceptionEnum.java
index 26d432bb..b79531fd 100644
---
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/enums/ApiExceptionEnum.java
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/enums/ApiExceptionEnum.java
@@ -61,7 +61,7 @@ public enum ApiExceptionEnum {
// Command Exceptions -- 18000 ~ 18999
COMMAND_NOT_FOUND(18000, LocaleKeys.COMMAND_NOT_FOUND),
- COMMAND_NOT_SUPPORTED(18000, LocaleKeys.COMMAND_NOT_SUPPORTED),
+ COMMAND_NOT_SUPPORTED(18001, LocaleKeys.COMMAND_NOT_SUPPORTED),
// LLM Exceptions -- 19000 ~ 19999
PLATFORM_NOT_FOUND(19000, LocaleKeys.PLATFORM_NOT_FOUND),
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/CommandDTO.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/CommandDTO.java
index 5ea67aa0..d0c30213 100644
---
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/CommandDTO.java
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/dto/CommandDTO.java
@@ -25,12 +25,9 @@ import
org.apache.bigtop.manager.server.model.dto.command.ComponentCommandDTO;
import org.apache.bigtop.manager.server.model.dto.command.HostCommandDTO;
import org.apache.bigtop.manager.server.model.dto.command.ServiceCommandDTO;
-import org.apache.commons.text.CaseUtils;
-
import lombok.Data;
import java.io.Serializable;
-import java.text.MessageFormat;
import java.util.List;
@Data
@@ -51,17 +48,4 @@ public class CommandDTO implements Serializable {
private List<ServiceCommandDTO> serviceCommands;
private List<ComponentCommandDTO> componentCommands;
-
- public String getContext() {
- if (clusterId == null) {
- return "Create Cluster";
- }
-
- if (command == null) {
- return MessageFormat.format("{0} for {1}", customCommand,
commandLevel.toLowerCase());
- } else {
- return MessageFormat.format(
- "{0} for {1}", CaseUtils.toCamelCase(command.name(),
true), commandLevel.toLowerCase());
- }
- }
}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/CommandReq.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/CommandReq.java
index 3194f4c6..7b597ee6 100644
---
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/CommandReq.java
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/model/req/CommandReq.java
@@ -32,7 +32,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@@ -52,16 +51,15 @@ public class CommandReq {
@NotNull @Schema(example = "cluster")
private CommandLevel commandLevel;
- @NotNull(groups =
{CommandGroupSequenceProvider.ClusterCommandGroup.class}) @Schema(description =
"Command details for cluster level command")
+ @Schema(description = "Command details for cluster level command")
private ClusterCommandReq clusterCommand;
- @NotNull(groups = {CommandGroupSequenceProvider.HostCommandGroup.class})
@Schema(description = "Command details for host level command")
+ @Schema(description = "Command details for host level command")
private List<@Valid HostCommandReq> hostCommands;
- @NotEmpty(groups =
{CommandGroupSequenceProvider.ServiceCommandGroup.class})
@Schema(description = "Command details for service level command")
private List<@Valid ServiceCommandReq> serviceCommands;
- @NotNull(groups =
{CommandGroupSequenceProvider.ComponentCommandGroup.class}) @Schema(description
= "Command details for component level command")
+ @Schema(description = "Command details for component level command")
private List<@Valid ComponentCommandReq> componentCommands;
}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackDAGUtils.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackDAGUtils.java
new file mode 100644
index 00000000..994170f2
--- /dev/null
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackDAGUtils.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.bigtop.manager.server.utils;
+
+import org.apache.bigtop.manager.common.enums.Command;
+import org.apache.bigtop.manager.server.exception.ServerException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StackDAGUtils {
+
+ public static List<String> orderTodoList(List<String>
componentCommandNames) {
+ try {
+ List<String> orderedList =
+ StackUtils.DAG.getAllNodesList().isEmpty() ? new
ArrayList<>() : StackUtils.DAG.topologicalSort();
+
+ // Re-order the commands, since order.json does not contain all
commands,
+ // only contains which has dependencies, we need to add the rest
to the end.
+ orderedList.retainAll(componentCommandNames);
+ componentCommandNames.removeAll(orderedList);
+ orderedList.addAll(componentCommandNames);
+
+ return orderedList;
+ } catch (Exception e) {
+ throw new ServerException(e);
+ }
+ }
+
+ public static List<String> getTodoList(List<String> componentNames,
Command command) {
+ try {
+ List<String> orderedList =
+ StackUtils.DAG.getAllNodesList().isEmpty() ? new
ArrayList<>() : StackUtils.DAG.topologicalSort();
+ List<String> componentCommandNames = new
ArrayList<>(componentNames.stream()
+ .map(x -> x + "-" + command.name().toUpperCase())
+ .toList());
+
+ // Re-order the commands, since order.json does not contain all
commands,
+ // only contains which has dependencies, we need to add the rest
to the end.
+ orderedList.retainAll(componentCommandNames);
+ componentCommandNames.removeAll(orderedList);
+ orderedList.addAll(componentCommandNames);
+
+ return orderedList;
+ } catch (Exception e) {
+ throw new ServerException(e);
+ }
+ }
+}
diff --git
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
index b8e7fba4..7eaad4a1 100644
---
a/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
+++
b/bigtop-manager-server/src/main/java/org/apache/bigtop/manager/server/utils/StackUtils.java
@@ -18,6 +18,7 @@
*/
package org.apache.bigtop.manager.server.utils;
+import org.apache.bigtop.manager.common.constants.ComponentCategories;
import org.apache.bigtop.manager.common.enums.Command;
import org.apache.bigtop.manager.common.utils.CaseUtils;
import org.apache.bigtop.manager.common.utils.JsonUtils;
@@ -267,4 +268,14 @@ public class StackUtils {
throw new ServerException("Service not found by component name: " +
componentName);
}
+
+ public static Boolean isServerComponent(String componentName) {
+ ComponentDTO componentDTO = getComponentDTO(componentName);
+ return
componentDTO.getCategory().equalsIgnoreCase(ComponentCategories.SERVER);
+ }
+
+ public static Boolean isClientComponent(String componentName) {
+ ComponentDTO componentDTO = getComponentDTO(componentName);
+ return
componentDTO.getCategory().equalsIgnoreCase(ComponentCategories.CLIENT);
+ }
}