🔨 执行命令.

This commit is contained in:
lijiahang
2024-03-14 19:46:05 +08:00
parent e98bace51b
commit 6bd2640af7
25 changed files with 900 additions and 181 deletions

View File

@@ -7,6 +7,7 @@ import com.orion.ops.framework.web.core.annotation.RestWrapper;
import com.orion.ops.module.asset.define.operator.ExecOperatorType;
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
import com.orion.ops.module.asset.entity.request.exec.ExecInterruptRequest;
import com.orion.ops.module.asset.entity.request.exec.ReExecCommandRequest;
import com.orion.ops.module.asset.entity.vo.ExecCommandVO;
import com.orion.ops.module.asset.service.ExecService;
import io.swagger.v3.oas.annotations.Operation;
@@ -41,10 +42,18 @@ public class ExecController {
@PostMapping("/exec-command")
@Operation(summary = "批量执行命令")
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
public ExecCommandVO execCommand(@RequestBody ExecCommandRequest request) {
public ExecCommandVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
return execService.execCommand(request);
}
@OperatorLog(ExecOperatorType.EXEC_COMMAND)
@PostMapping("/re-exec-command")
@Operation(summary = "重新执行命令")
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
public ExecCommandVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
return execService.reExecCommand(request.getLogId());
}
@OperatorLog(ExecOperatorType.INTERRUPT_EXEC)
@PutMapping("/interrupt")
@Operation(summary = "中断执行命令")
@@ -66,7 +75,6 @@ public class ExecController {
}
// TODO tail log
// TODO 重新执行
// TODO 删除时 中断
// TODO parameterSchema 存储
}

View File

@@ -4,6 +4,8 @@ import com.orion.ops.framework.mybatis.core.mapper.IMapper;
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 批量执行主机日志 Mapper 接口
*
@@ -14,4 +16,18 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ExecHostLogDAO extends IMapper<ExecHostLogDO> {
/**
* 通过 logId 查询
*
* @param logId logId
* @return rows
*/
default List<ExecHostLogDO> selectByLogId(Long logId) {
return this.of()
.createWrapper()
.eq(ExecHostLogDO::getLogId, logId)
.then()
.list();
}
}

View File

@@ -22,9 +22,6 @@ import java.util.List;
@Schema(name = "ExecCommandRequest", description = "批量执行命令 请求对象")
public class ExecCommandRequest {
@Schema(description = "执行模板id")
private Long templateId;
@Size(max = 128)
@Schema(description = "执行描述")
private String description;

View File

@@ -0,0 +1,24 @@
package com.orion.ops.module.asset.entity.request.exec;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* 重新执行命令 请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/3/11 11:46
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "ReExecCommandRequest", description = "重新执行命令 请求对象")
public class ReExecCommandRequest {
@NonNull
@Schema(description = "logId")
private Long logId;
}

View File

@@ -20,6 +20,14 @@ public interface ExecService {
*/
ExecCommandVO execCommand(ExecCommandRequest request);
/**
* 重新执行命令
*
* @param id id
* @return result
*/
ExecCommandVO reExecCommand(Long id);
/**
* 中断命令执行
*

View File

@@ -9,6 +9,9 @@ import com.orion.ops.module.asset.convert.ExecHostLogConvert;
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
import com.orion.ops.module.asset.handler.host.exec.handler.IExecCommandHandler;
import com.orion.ops.module.asset.handler.host.exec.handler.IExecTaskHandler;
import com.orion.ops.module.asset.handler.host.exec.manager.ExecManager;
import com.orion.ops.module.asset.service.ExecHostLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -16,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
/**
* 批量执行主机日志 服务实现类
@@ -31,6 +35,9 @@ public class ExecHostLogServiceImpl implements ExecHostLogService {
@Resource
private ExecHostLogDAO execHostLogDAO;
@Resource
private ExecManager execManager;
@Override
public List<ExecHostLogVO> getExecHostLogList(Long logId) {
return execHostLogDAO.of()
@@ -65,6 +72,14 @@ public class ExecHostLogServiceImpl implements ExecHostLogService {
// 检查数据是否存在
ExecHostLogDO record = execHostLogDAO.selectById(id);
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
// 中断
Optional.ofNullable(record.getLogId())
.map(execManager::getTask)
.map(IExecTaskHandler::getHandlers)
.flatMap(s -> s.stream()
.filter(h -> h.getHostId().equals(record.getHostId()))
.findFirst())
.ifPresent(IExecCommandHandler::interrupted);
// 删除
int effect = execHostLogDAO.deleteById(id);
log.info("ExecHostLogService-deleteExecHostLogById id: {}, effect: {}", id, effect);

View File

@@ -18,6 +18,8 @@ import com.orion.ops.module.asset.entity.request.exec.ExecLogQueryRequest;
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
import com.orion.ops.module.asset.entity.vo.ExecLogStatusVO;
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
import com.orion.ops.module.asset.handler.host.exec.handler.IExecTaskHandler;
import com.orion.ops.module.asset.handler.host.exec.manager.ExecManager;
import com.orion.ops.module.asset.service.ExecHostLogService;
import com.orion.ops.module.asset.service.ExecLogService;
import lombok.extern.slf4j.Slf4j;
@@ -26,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -48,6 +51,9 @@ public class ExecLogServiceImpl implements ExecLogService {
@Resource
private ExecHostLogService execHostLogService;
@Resource
private ExecManager execManager;
@Override
public DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request) {
// 条件
@@ -74,6 +80,7 @@ public class ExecLogServiceImpl implements ExecLogService {
List<ExecHostLogVO> hostList = execHostLogDAO.of()
.createWrapper()
.select(ExecHostLogDO::getId,
ExecHostLogDO::getLogId,
ExecHostLogDO::getStatus,
ExecHostLogDO::getStartTime,
ExecHostLogDO::getFinishTime,
@@ -101,6 +108,8 @@ public class ExecLogServiceImpl implements ExecLogService {
// 检查数据是否存在
ExecLogDO record = execLogDAO.selectById(id);
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
// 中断命令执行
this.interruptedTask(Lists.singleton(id));
// 删除执行日志
int effect = execLogDAO.deleteById(id);
// 删除主机日志
@@ -115,6 +124,8 @@ public class ExecLogServiceImpl implements ExecLogService {
@Transactional(rollbackFor = Exception.class)
public Integer deleteExecLogByIdList(List<Long> idList) {
log.info("ExecLogService-deleteExecLogByIdList idList: {}", idList);
// 中断命令执行
this.interruptedTask(idList);
// 删除执行日志
int effect = execLogDAO.deleteBatchIds(idList);
// 删除主机日志
@@ -138,6 +149,8 @@ public class ExecLogServiceImpl implements ExecLogService {
.collect(Collectors.toList());
int effect = 0;
if (!idList.isEmpty()) {
// 中断命令执行
this.interruptedTask(idList);
// 删除执行日志
effect = execLogDAO.delete(wrapper);
// 删除主机日志
@@ -170,4 +183,16 @@ public class ExecLogServiceImpl implements ExecLogService {
.orderByDesc(ExecLogDO::getId);
}
/**
* 中断任务
*
* @param idList idList
*/
private void interruptedTask(List<Long> idList) {
idList.stream()
.map(execManager::getTask)
.filter(Objects::nonNull)
.forEach(IExecTaskHandler::interrupted);
}
}

View File

@@ -61,7 +61,7 @@ import java.util.stream.Collectors;
public class ExecServiceImpl implements ExecService {
private static final ReplacementFormatter FORMATTER = ReplacementFormatters.create("@{{ ", " }}")
.noMatchStrategy(NoMatchStrategy.EMPTY);
.noMatchStrategy(NoMatchStrategy.KEEP);
@Resource
private FileClient logsFileClient;
@@ -124,23 +124,10 @@ public class ExecServiceImpl implements ExecService {
.build();
}).collect(Collectors.toList());
execHostLogDAO.insertBatch(execHostLogs);
// 开始执行
ExecCommandDTO exec = ExecCommandDTO.builder()
.logId(execId)
.timeout(request.getTimeout())
.hosts(execHostLogs.stream()
.map(s -> ExecCommandHostDTO.builder()
.hostId(s.getHostId())
.hostLogId(s.getId())
.command(s.getCommand())
.timeout(request.getTimeout())
.logPath(s.getLogPath())
.build())
.collect(Collectors.toList()))
.build();
ExecTaskExecutors.start(exec);
// 操作日志
OperatorLogs.add(OperatorLogs.ID, execId);
// 开始执行
this.startExec(execLog, execHostLogs);
// 返回
List<ExecCommandHostVO> hostResult = execHostLogs.stream()
.map(s -> ExecCommandHostVO.builder()
@@ -154,6 +141,29 @@ public class ExecServiceImpl implements ExecService {
.build();
}
@Override
public ExecCommandVO reExecCommand(Long logId) {
log.info("ExecService.reExecCommand start logId: {}", logId);
// 获取执行记录
ExecLogDO execLog = execLogDAO.selectById(logId);
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
// 获取执行主机
List<ExecHostLogDO> hostLogs = execHostLogDAO.selectByLogId(logId);
Valid.notEmpty(hostLogs, ErrorMessage.DATA_ABSENT);
List<Long> hostIdList = hostLogs.stream()
.map(ExecHostLogDO::getHostId)
.collect(Collectors.toList());
// 调用执行方法
ExecCommandRequest request = ExecCommandRequest.builder()
.description(execLog.getDescription())
.timeout(execLog.getTimeout())
.command(execLog.getCommand())
.parameter(hostLogs.get(0).getParameter())
.hostIdList(hostIdList)
.build();
return this.execCommand(request);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void interruptExec(Long logId) {
@@ -250,6 +260,29 @@ public class ExecServiceImpl implements ExecService {
}
}
/**
* 开始执行命令
*
* @param execLog execLog
* @param execHostLogs hostLogs
*/
private void startExec(ExecLogDO execLog, List<ExecHostLogDO> execHostLogs) {
ExecCommandDTO exec = ExecCommandDTO.builder()
.logId(execLog.getId())
.timeout(execLog.getTimeout())
.hosts(execHostLogs.stream()
.map(s -> ExecCommandHostDTO.builder()
.hostId(s.getHostId())
.hostLogId(s.getId())
.command(s.getCommand())
.timeout(execLog.getTimeout())
.logPath(s.getLogPath())
.build())
.collect(Collectors.toList()))
.build();
ExecTaskExecutors.start(exec);
}
/**
* 构建日志路径
*