🎨 修改执行模块代码结构.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
### 批量执行命令
|
||||
POST {{baseUrl}}/asset/exec/exec-command
|
||||
POST {{baseUrl}}/asset/exec-command/exec
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
@@ -11,9 +11,17 @@ Authorization: {{token}}
|
||||
"hostIdList": [1]
|
||||
}
|
||||
|
||||
### 批量执行命令
|
||||
POST {{baseUrl}}/asset/exec-command/re-exec
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"logId": 1
|
||||
}
|
||||
|
||||
### 中断执行命令
|
||||
POST {{baseUrl}}/asset/exec/interrupt-command
|
||||
POST {{baseUrl}}/asset/exec-command/interrupt
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
@@ -22,19 +30,4 @@ Authorization: {{token}}
|
||||
}
|
||||
|
||||
|
||||
### 查看执行日志
|
||||
POST {{baseUrl}}/asset/exec/tail-log
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"execId": 56
|
||||
}
|
||||
|
||||
|
||||
### 下载执行日志文件
|
||||
GET {{baseUrl}}/asset/exec/download-log?id=83
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
###
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.orion.ops.module.asset.controller;
|
||||
|
||||
import com.orion.lang.define.wrapper.HttpWrapper;
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.ops.framework.biz.operator.log.core.enums.ReturnType;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.asset.define.operator.ExecCommandOperatorType;
|
||||
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.ExecLogVO;
|
||||
import com.orion.ops.module.asset.enums.ExecSourceEnum;
|
||||
import com.orion.ops.module.asset.service.ExecCommandService;
|
||||
import com.orion.ops.module.asset.service.ExecLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 批量执行
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 11:44
|
||||
*/
|
||||
@Tag(name = "asset - 批量执行服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/exec-command")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class ExecCommandController {
|
||||
|
||||
private static final String SOURCE = ExecSourceEnum.BATCH.name();
|
||||
|
||||
@Resource
|
||||
private ExecCommandService execCommandService;
|
||||
|
||||
@Resource
|
||||
private ExecLogService execLogService;
|
||||
|
||||
@OperatorLog(value = ExecCommandOperatorType.EXEC, ret = ReturnType.IGNORE)
|
||||
@PostMapping("/exec")
|
||||
@Operation(summary = "批量执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command:exec')")
|
||||
public ExecLogVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
|
||||
return execCommandService.execCommand(request);
|
||||
}
|
||||
|
||||
@OperatorLog(value = ExecCommandOperatorType.EXEC, ret = ReturnType.IGNORE)
|
||||
@PostMapping("/re-exec")
|
||||
@Operation(summary = "重新执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command:exec')")
|
||||
public ExecLogVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
|
||||
return execCommandService.reExecCommand(request.getLogId());
|
||||
}
|
||||
|
||||
@OperatorLog(ExecCommandOperatorType.INTERRUPT_EXEC)
|
||||
@PutMapping("/interrupt")
|
||||
@Operation(summary = "中断执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command:interrupt')")
|
||||
public HttpWrapper<?> interruptExecCommand(@RequestBody ExecInterruptRequest request) {
|
||||
Long logId = Valid.notNull(request.getLogId());
|
||||
execLogService.interruptExec(logId, SOURCE);
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
@OperatorLog(ExecCommandOperatorType.INTERRUPT_HOST)
|
||||
@PutMapping("/interrupt-host")
|
||||
@Operation(summary = "中断执行主机命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command:interrupt')")
|
||||
public HttpWrapper<?> interruptHostExecCommand(@RequestBody ExecInterruptRequest request) {
|
||||
Long hostLogId = Valid.notNull(request.getHostLogId());
|
||||
execLogService.interruptHostExec(hostLogId, SOURCE);
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
### 查询批量执行日志
|
||||
GET {{baseUrl}}/asset/exec-command-log/get?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 分页查询批量执行日志
|
||||
POST {{baseUrl}}/asset/exec-command-log/query
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"id": "",
|
||||
"userId": "",
|
||||
"username": "",
|
||||
"description": "",
|
||||
"command": "",
|
||||
"status": ""
|
||||
}
|
||||
|
||||
|
||||
### 删除批量执行日志
|
||||
DELETE {{baseUrl}}/asset/exec-command-log/delete?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 批量删除批量执行日志
|
||||
DELETE {{baseUrl}}/asset/exec-command-log/batch-delete?idList=1,2,3
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 查看执行日志
|
||||
POST {{baseUrl}}/asset/exec-command-log/tail
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"execId": 56
|
||||
}
|
||||
|
||||
|
||||
### 下载执行日志文件
|
||||
GET {{baseUrl}}/asset/exec-command-log/download?id=83
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
###
|
||||
@@ -7,8 +7,9 @@ import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.asset.define.operator.ExecOperatorType;
|
||||
import com.orion.ops.module.asset.define.operator.ExecCommandLogOperatorType;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||
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;
|
||||
@@ -24,6 +25,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -38,9 +40,11 @@ import java.util.List;
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/exec-log")
|
||||
@RequestMapping("/asset/exec-command-log")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class ExecLogController {
|
||||
public class ExecCommandLogController {
|
||||
|
||||
private static final String SOURCE = ExecSourceEnum.BATCH.name();
|
||||
|
||||
@Resource
|
||||
private ExecLogService execLogService;
|
||||
@@ -51,25 +55,25 @@ public class ExecLogController {
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@PostMapping("/query")
|
||||
@Operation(summary = "分页查询执行日志")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:query')")
|
||||
public DataGrid<ExecLogVO> getExecLogPage(@Validated(Page.class) @RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(ExecSourceEnum.BATCH.name());
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:query')")
|
||||
public DataGrid<ExecLogVO> getExecCommandLogPage(@Validated(Page.class) @RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(SOURCE);
|
||||
return execLogService.getExecLogPage(request);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "查询执行日志")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:query')")
|
||||
public ExecLogVO getExecLog(@RequestParam("id") Long id) {
|
||||
return execLogService.getExecLog(id, ExecSourceEnum.BATCH.name());
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:query')")
|
||||
public ExecLogVO getExecCommandLog(@RequestParam("id") Long id) {
|
||||
return execLogService.getExecLog(id, SOURCE);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/host-list")
|
||||
@Operation(summary = "查询全部执行主机日志")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:query')")
|
||||
public List<ExecHostLogVO> getExecHostLogList(@RequestParam("logId") Long logId) {
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:query')")
|
||||
public List<ExecHostLogVO> getExecCommandHostLogList(@RequestParam("logId") Long logId) {
|
||||
return execHostLogService.getExecHostLogList(logId);
|
||||
}
|
||||
|
||||
@@ -77,64 +81,80 @@ public class ExecLogController {
|
||||
@GetMapping("/status")
|
||||
@Operation(summary = "查询命令执行状态")
|
||||
@Parameter(name = "idList", description = "idList", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:query')")
|
||||
public ExecLogStatusVO getExecLogStatus(@RequestParam("idList") List<Long> idList) {
|
||||
return execLogService.getExecLogStatus(idList);
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:query')")
|
||||
public ExecLogStatusVO getExecCommandLogStatus(@RequestParam("idList") List<Long> idList) {
|
||||
return execLogService.getExecLogStatus(idList, SOURCE);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/history")
|
||||
@Operation(summary = "查询执行历史")
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec-log:query', 'asset:exec:exec-command')")
|
||||
public List<ExecLogVO> getExecLogHistory(@Validated(Page.class) ExecLogQueryRequest request) {
|
||||
request.setSource(ExecSourceEnum.BATCH.name());
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec-command-log:query', 'asset:exec-command:exec')")
|
||||
public List<ExecLogVO> getExecCommandLogHistory(@Validated(Page.class) ExecLogQueryRequest request) {
|
||||
request.setSource(SOURCE);
|
||||
request.setUserId(SecurityUtils.getLoginUserId());
|
||||
return execLogService.getExecHistory(request);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.DELETE_LOG)
|
||||
@OperatorLog(ExecCommandLogOperatorType.DELETE)
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除执行日志")
|
||||
@Parameter(name = "id", description = "id", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:delete')")
|
||||
public Integer deleteExecLog(@RequestParam("id") Long id) {
|
||||
return execLogService.deleteExecLogById(id);
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:delete')")
|
||||
public Integer deleteExecCommandLog(@RequestParam("id") Long id) {
|
||||
return execLogService.deleteExecLogById(id, SOURCE);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.DELETE_LOG)
|
||||
@OperatorLog(ExecCommandLogOperatorType.DELETE)
|
||||
@DeleteMapping("/batch-delete")
|
||||
@Operation(summary = "删除执行日志")
|
||||
@Parameter(name = "idList", description = "idList", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:delete')")
|
||||
public Integer batchDeleteExecLog(@RequestParam("idList") List<Long> idList) {
|
||||
return execLogService.deleteExecLogByIdList(idList);
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:delete')")
|
||||
public Integer batchDeleteExecCommandLog(@RequestParam("idList") List<Long> idList) {
|
||||
return execLogService.deleteExecLogByIdList(idList, SOURCE);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.DELETE_HOST_LOG)
|
||||
@OperatorLog(ExecCommandLogOperatorType.DELETE_HOST)
|
||||
@DeleteMapping("/delete-host")
|
||||
@Operation(summary = "删除执行主机日志")
|
||||
@Parameter(name = "id", description = "id", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:delete')")
|
||||
public Integer deleteExecHostLog(@RequestParam("id") Long id) {
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:delete')")
|
||||
public Integer deleteExecCommandHostLog(@RequestParam("id") Long id) {
|
||||
return execHostLogService.deleteExecHostLogById(id);
|
||||
}
|
||||
|
||||
@PostMapping("/query-count")
|
||||
@Operation(summary = "查询执行日志数量")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:management:clear')")
|
||||
public Long getExecLogCount(@RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(ExecSourceEnum.BATCH.name());
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:management:clear')")
|
||||
public Long getExecCommandLogCount(@RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(SOURCE);
|
||||
return execLogService.queryExecLogCount(request);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.CLEAR_LOG)
|
||||
@OperatorLog(ExecCommandLogOperatorType.CLEAR)
|
||||
@PostMapping("/clear")
|
||||
@Operation(summary = "清空执行日志")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-log:management:clear')")
|
||||
public Integer clearExecLog(@RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(ExecSourceEnum.BATCH.name());
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-command-log:management:clear')")
|
||||
public Integer clearExecCommandLog(@RequestBody ExecLogQueryRequest request) {
|
||||
request.setSource(SOURCE);
|
||||
return execLogService.clearExecLog(request);
|
||||
}
|
||||
|
||||
@PostMapping("/tail")
|
||||
@Operation(summary = "查看执行日志")
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec-command-log:query', 'asset:exec-command:exec')")
|
||||
public String getExecCommandLogTailToken(@Validated @RequestBody ExecLogTailRequest request) {
|
||||
request.setSource(SOURCE);
|
||||
return execLogService.getExecLogTailToken(request);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecCommandLogOperatorType.DOWNLOAD)
|
||||
@GetMapping("/download")
|
||||
@Operation(summary = "下载执行日志")
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec-command-log:query', 'asset:exec-command:exec')")
|
||||
public void downloadExecCommandLogFile(@RequestParam("id") Long id, HttpServletResponse response) {
|
||||
execLogService.downloadLogFile(id, SOURCE, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
package com.orion.ops.module.asset.controller;
|
||||
|
||||
import com.orion.lang.define.wrapper.HttpWrapper;
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.ops.framework.biz.operator.log.core.enums.ReturnType;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
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.ExecLogTailRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ReExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
import com.orion.ops.module.asset.service.ExecService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 批量执行
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 11:44
|
||||
*/
|
||||
@Tag(name = "asset - 批量执行服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/exec")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class ExecController {
|
||||
|
||||
@Resource
|
||||
private ExecService execService;
|
||||
|
||||
@OperatorLog(value = ExecOperatorType.EXEC_COMMAND, ret = ReturnType.IGNORE)
|
||||
@PostMapping("/exec-command")
|
||||
@Operation(summary = "批量执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||
public ExecLogVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
|
||||
return execService.execCommand(request);
|
||||
}
|
||||
|
||||
@OperatorLog(value = ExecOperatorType.EXEC_COMMAND, ret = ReturnType.IGNORE)
|
||||
@PostMapping("/re-exec-command")
|
||||
@Operation(summary = "重新执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||
public ExecLogVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
|
||||
return execService.reExecCommand(request.getLogId());
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.INTERRUPT_EXEC)
|
||||
@PutMapping("/interrupt")
|
||||
@Operation(summary = "中断执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:interrupt-exec')")
|
||||
public HttpWrapper<?> interruptExec(@RequestBody ExecInterruptRequest request) {
|
||||
Long logId = Valid.notNull(request.getLogId());
|
||||
execService.interruptExec(logId);
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.INTERRUPT_HOST)
|
||||
@PutMapping("/interrupt-host")
|
||||
@Operation(summary = "中断执行主机命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:interrupt-exec')")
|
||||
public HttpWrapper<?> interruptHostExec(@RequestBody ExecInterruptRequest request) {
|
||||
Long hostLogId = Valid.notNull(request.getHostLogId());
|
||||
execService.interruptHostExec(hostLogId);
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/tail-log")
|
||||
@Operation(summary = "查看执行日志")
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec:exec-command', 'asset:exec-log:query')")
|
||||
public String getExecLogTailToken(@Validated @RequestBody ExecLogTailRequest request) {
|
||||
return execService.getExecLogTailToken(request);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.DOWNLOAD_HOST_LOG)
|
||||
@GetMapping("/download-log")
|
||||
@Operation(summary = "下载执行日志")
|
||||
@PreAuthorize("@ss.hasAnyPermission('asset:exec:exec-command', 'asset:exec-log:query')")
|
||||
public void downloadExecLogFile(@RequestParam("id") Long id, HttpServletResponse response) {
|
||||
execService.downloadLogFile(id, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
### 查询批量执行日志
|
||||
GET {{baseUrl}}/asset/exec-log/get?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 分页查询批量执行日志
|
||||
POST {{baseUrl}}/asset/exec-log/query
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"id": "",
|
||||
"userId": "",
|
||||
"username": "",
|
||||
"source": "",
|
||||
"sourceId": "",
|
||||
"description": "",
|
||||
"command": "",
|
||||
"status": ""
|
||||
}
|
||||
|
||||
|
||||
### 删除批量执行日志
|
||||
DELETE {{baseUrl}}/asset/exec-log/delete?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 批量删除批量执行日志
|
||||
DELETE {{baseUrl}}/asset/exec-log/batch-delete?idList=1,2,3
|
||||
Authorization: {{token}}
|
||||
|
||||
###
|
||||
@@ -67,6 +67,7 @@ public class HostConnectLogController {
|
||||
|
||||
@PostMapping("/query-count")
|
||||
@Operation(summary = "查询主机连接日志数量")
|
||||
@PreAuthorize("@ss.hasPermission('asset:host-connect-log:management:clear')")
|
||||
public Long getHostConnectLogCount(@RequestBody HostConnectLogQueryRequest request) {
|
||||
return hostConnectLogService.getHostConnectLogCount(request);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,22 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface ExecLogDAO extends IMapper<ExecLogDO> {
|
||||
|
||||
/**
|
||||
* 通过 id 和 source 查询
|
||||
*
|
||||
* @param id id
|
||||
* @param source source
|
||||
* @return log
|
||||
*/
|
||||
default ExecLogDO selectByIdSource(Long id, String source) {
|
||||
return this.of()
|
||||
.createWrapper()
|
||||
.eq(ExecLogDO::getId, id)
|
||||
.eq(ExecLogDO::getSource, source)
|
||||
.then()
|
||||
.getOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取执行历史
|
||||
*
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.orion.ops.module.asset.define.operator;
|
||||
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.Module;
|
||||
import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
|
||||
|
||||
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.H;
|
||||
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.L;
|
||||
|
||||
/**
|
||||
* 批量执行 操作记录类型
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.1
|
||||
* @since 2024-3-11 11:31
|
||||
*/
|
||||
@Module("asset:exec-command-log")
|
||||
public class ExecCommandLogOperatorType extends InitializingOperatorTypes {
|
||||
|
||||
public static final String DELETE = "exec-command-log:delete";
|
||||
|
||||
public static final String DELETE_HOST = "exec-command-log:delete-host";
|
||||
|
||||
public static final String CLEAR = "exec-command-log:clear";
|
||||
|
||||
public static final String DOWNLOAD = "exec-command-log:download";
|
||||
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(H, DELETE, "删除执行记录 <sb>${count}</sb> 条"),
|
||||
new OperatorType(H, CLEAR, "清理执行记录 <sb>${count}</sb> 条"),
|
||||
new OperatorType(H, DELETE_HOST, "删除主机执行记录 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
new OperatorType(L, DOWNLOAD, "下载主机执行日志 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.orion.ops.module.asset.define.operator;
|
||||
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.Module;
|
||||
import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
|
||||
|
||||
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.M;
|
||||
|
||||
/**
|
||||
* 批量执行 操作记录类型
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.1
|
||||
* @since 2024-3-11 11:31
|
||||
*/
|
||||
@Module("asset:exec-command-log")
|
||||
public class ExecCommandOperatorType extends InitializingOperatorTypes {
|
||||
|
||||
public static final String EXEC = "exec-command:exec";
|
||||
|
||||
public static final String INTERRUPT_EXEC = "exec-command:interrupt-exec";
|
||||
|
||||
public static final String INTERRUPT_HOST = "exec-command:interrupt-host";
|
||||
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(M, EXEC, "执行主机命令"),
|
||||
new OperatorType(M, INTERRUPT_EXEC, "中断执行命令"),
|
||||
new OperatorType(M, INTERRUPT_HOST, "中断主机执行命令 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.orion.ops.module.asset.define.operator;
|
||||
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.Module;
|
||||
import com.orion.ops.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
|
||||
|
||||
import static com.orion.ops.framework.biz.operator.log.core.enums.OperatorRiskLevel.*;
|
||||
|
||||
/**
|
||||
* 批量执行 操作记录类型
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.1
|
||||
* @since 2024-3-11 11:31
|
||||
*/
|
||||
@Module("asset:exec")
|
||||
public class ExecOperatorType extends InitializingOperatorTypes {
|
||||
|
||||
public static final String EXEC_COMMAND = "exec:exec-command";
|
||||
|
||||
public static final String INTERRUPT_EXEC = "exec:interrupt-exec";
|
||||
|
||||
public static final String INTERRUPT_HOST = "exec:interrupt-host";
|
||||
|
||||
public static final String DELETE_LOG = "exec:delete-log";
|
||||
|
||||
public static final String CLEAR_LOG = "exec:clear-log";
|
||||
|
||||
public static final String DELETE_HOST_LOG = "exec:delete-host-log";
|
||||
|
||||
public static final String DOWNLOAD_HOST_LOG = "exec:download-host-log";
|
||||
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(M, EXEC_COMMAND, "执行主机命令"),
|
||||
new OperatorType(M, INTERRUPT_EXEC, "中断执行命令"),
|
||||
new OperatorType(M, INTERRUPT_HOST, "中断主机执行命令 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
new OperatorType(H, DELETE_LOG, "删除执行记录 <sb>${count}</sb> 条"),
|
||||
new OperatorType(H, CLEAR_LOG, "清理执行记录 <sb>${count}</sb> 条"),
|
||||
new OperatorType(H, DELETE_HOST_LOG, "删除主机执行记录 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
new OperatorType(L, DOWNLOAD_HOST_LOG, "下载主机执行日志 <sb>${logId}</sb> <sb>${hostName}</sb>"),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,9 @@ import java.util.List;
|
||||
@Schema(name = "ExecLogTailRequest", description = "执行日志查看 请求对象")
|
||||
public class ExecLogTailRequest {
|
||||
|
||||
@Schema(description = "执行来源")
|
||||
private String source;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "执行id")
|
||||
private Long execId;
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.orion.ops.module.asset.interceptor;
|
||||
import com.orion.lang.utils.Urls;
|
||||
import com.orion.ops.framework.common.constant.ExtraFieldConst;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||
import com.orion.ops.module.asset.service.ExecService;
|
||||
import com.orion.ops.module.asset.service.ExecLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
@@ -26,7 +26,7 @@ import java.util.Map;
|
||||
public class ExecLogTailInterceptor implements HandshakeInterceptor {
|
||||
|
||||
@Resource
|
||||
private ExecService execService;
|
||||
private ExecLogService execLogService;
|
||||
|
||||
@Override
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
|
||||
@@ -34,7 +34,7 @@ public class ExecLogTailInterceptor implements HandshakeInterceptor {
|
||||
String token = Urls.getUrlSource(request.getURI().getPath());
|
||||
log.info("ExecLogTailInterceptor-beforeHandshake start token: {}", token);
|
||||
// 获取日志数据
|
||||
ExecLogTailDTO info = execService.getExecLogTailInfo(token);
|
||||
ExecLogTailDTO info = execLogService.getExecLogTailInfo(token);
|
||||
if (info == null) {
|
||||
log.error("ExecLogTailInterceptor-beforeHandshake absent token: {}", token);
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandExecRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
|
||||
/**
|
||||
* 批量执行服务
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 12:02
|
||||
*/
|
||||
public interface ExecCommandService {
|
||||
|
||||
/**
|
||||
* 批量执行命令
|
||||
*
|
||||
* @param request request
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO execCommand(ExecCommandRequest request);
|
||||
|
||||
/**
|
||||
* 批量执行命令
|
||||
*
|
||||
* @param request request
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO execCommandWithSource(ExecCommandExecRequest request);
|
||||
|
||||
/**
|
||||
* 重新执行命令
|
||||
*
|
||||
* @param logId logId
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO reExecCommand(Long logId);
|
||||
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogStatusVO;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -45,9 +48,28 @@ public interface ExecLogService {
|
||||
* 获取执行日志状态
|
||||
*
|
||||
* @param idList idList
|
||||
* @param source source
|
||||
* @return status
|
||||
*/
|
||||
ExecLogStatusVO getExecLogStatus(List<Long> idList);
|
||||
ExecLogStatusVO getExecLogStatus(List<Long> idList, String source);
|
||||
|
||||
/**
|
||||
* 删除执行日志
|
||||
*
|
||||
* @param id id
|
||||
* @param source source
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteExecLogById(Long id, String source);
|
||||
|
||||
/**
|
||||
* 批量删除批量执行日志
|
||||
*
|
||||
* @param idList idList
|
||||
* @param source source
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteExecLogByIdList(List<Long> idList, String source);
|
||||
|
||||
/**
|
||||
* 查询批量执行日志数量
|
||||
@@ -57,22 +79,6 @@ public interface ExecLogService {
|
||||
*/
|
||||
Long queryExecLogCount(ExecLogQueryRequest request);
|
||||
|
||||
/**
|
||||
* 删除执行日志
|
||||
*
|
||||
* @param id id
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteExecLogById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除批量执行日志
|
||||
*
|
||||
* @param idList idList
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteExecLogByIdList(List<Long> idList);
|
||||
|
||||
/**
|
||||
* 清理执行日志
|
||||
*
|
||||
@@ -81,4 +87,45 @@ public interface ExecLogService {
|
||||
*/
|
||||
Integer clearExecLog(ExecLogQueryRequest request);
|
||||
|
||||
/**
|
||||
* 中断命令执行
|
||||
*
|
||||
* @param logId logId
|
||||
* @param source source
|
||||
*/
|
||||
void interruptExec(Long logId, String source);
|
||||
|
||||
/**
|
||||
* 中断命令执行
|
||||
*
|
||||
* @param hostLogId hostLogId
|
||||
* @param source source
|
||||
*/
|
||||
void interruptHostExec(Long hostLogId, String source);
|
||||
|
||||
/**
|
||||
* 查看执行日志
|
||||
*
|
||||
* @param request request
|
||||
* @return token
|
||||
*/
|
||||
String getExecLogTailToken(ExecLogTailRequest request);
|
||||
|
||||
/**
|
||||
* 获取查看执行日志参数
|
||||
*
|
||||
* @param token token
|
||||
* @return log
|
||||
*/
|
||||
ExecLogTailDTO getExecLogTailInfo(String token);
|
||||
|
||||
/**
|
||||
* 下载执行日志文件
|
||||
*
|
||||
* @param id id
|
||||
* @param source source
|
||||
* @param response response
|
||||
*/
|
||||
void downloadLogFile(Long id, String source, HttpServletResponse response);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandExecRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 批量执行服务
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 12:02
|
||||
*/
|
||||
public interface ExecService {
|
||||
|
||||
/**
|
||||
* 批量执行命令
|
||||
*
|
||||
* @param request request
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO execCommand(ExecCommandRequest request);
|
||||
|
||||
/**
|
||||
* 批量执行命令
|
||||
*
|
||||
* @param request request
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO execCommandWithSource(ExecCommandExecRequest request);
|
||||
|
||||
/**
|
||||
* 重新执行命令
|
||||
*
|
||||
* @param logId logId
|
||||
* @return result
|
||||
*/
|
||||
ExecLogVO reExecCommand(Long logId);
|
||||
|
||||
/**
|
||||
* 中断命令执行
|
||||
*
|
||||
* @param logId logId
|
||||
*/
|
||||
void interruptExec(Long logId);
|
||||
|
||||
/**
|
||||
* 中断命令执行
|
||||
*
|
||||
* @param hostLogId hostLogId
|
||||
*/
|
||||
void interruptHostExec(Long hostLogId);
|
||||
|
||||
/**
|
||||
* 查看执行日志
|
||||
*
|
||||
* @param request request
|
||||
* @return token
|
||||
*/
|
||||
String getExecLogTailToken(ExecLogTailRequest request);
|
||||
|
||||
/**
|
||||
* 获取查看执行日志参数
|
||||
*
|
||||
* @param token token
|
||||
* @return log
|
||||
*/
|
||||
ExecLogTailDTO getExecLogTailInfo(String token);
|
||||
|
||||
/**
|
||||
* 下载执行日志文件
|
||||
*
|
||||
* @param id id
|
||||
* @param response response
|
||||
*/
|
||||
void downloadLogFile(Long id, HttpServletResponse response);
|
||||
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.exception.argument.InvalidArgumentException;
|
||||
import com.orion.lang.function.Functions;
|
||||
import com.orion.lang.id.UUIds;
|
||||
import com.orion.lang.utils.Objects1;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.collect.Maps;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.json.matcher.NoMatchStrategy;
|
||||
import com.orion.lang.utils.json.matcher.ReplacementFormatter;
|
||||
import com.orion.lang.utils.json.matcher.ReplacementFormatters;
|
||||
@@ -17,11 +13,9 @@ import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.constant.FieldConst;
|
||||
import com.orion.ops.framework.common.file.FileClient;
|
||||
import com.orion.ops.framework.common.security.LoginUser;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisStrings;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.ExecConvert;
|
||||
import com.orion.ops.module.asset.convert.ExecHostLogConvert;
|
||||
@@ -29,19 +23,14 @@ import com.orion.ops.module.asset.convert.ExecLogConvert;
|
||||
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
||||
import com.orion.ops.module.asset.dao.ExecLogDAO;
|
||||
import com.orion.ops.module.asset.dao.HostDAO;
|
||||
import com.orion.ops.module.asset.define.cache.ExecCacheKeyDefine;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecLogDO;
|
||||
import com.orion.ops.module.asset.entity.domain.HostDO;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecHostLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecParameterSchemaDTO;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandExecRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
import com.orion.ops.module.asset.entity.vo.HostConfigVO;
|
||||
import com.orion.ops.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.ops.module.asset.enums.ExecSourceEnum;
|
||||
import com.orion.ops.module.asset.enums.ExecStatusEnum;
|
||||
@@ -49,22 +38,17 @@ import com.orion.ops.module.asset.enums.HostConfigTypeEnum;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.ExecTaskExecutors;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.handler.IExecCommandHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.handler.IExecTaskHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.manager.ExecTaskManager;
|
||||
import com.orion.ops.module.asset.service.AssetAuthorizedDataService;
|
||||
import com.orion.ops.module.asset.service.ExecService;
|
||||
import com.orion.ops.module.asset.service.HostConfigService;
|
||||
import com.orion.web.servlet.web.Servlets;
|
||||
import com.orion.ops.module.asset.service.ExecCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -76,7 +60,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ExecServiceImpl implements ExecService {
|
||||
public class ExecCommandServiceImpl implements ExecCommandService {
|
||||
|
||||
private static final ReplacementFormatter FORMATTER = ReplacementFormatters.create("@{{ ", " }}")
|
||||
.noMatchStrategy(NoMatchStrategy.KEEP);
|
||||
@@ -98,12 +82,6 @@ public class ExecServiceImpl implements ExecService {
|
||||
@Resource
|
||||
private AssetAuthorizedDataService assetAuthorizedDataService;
|
||||
|
||||
@Resource
|
||||
private HostConfigService hostConfigService;
|
||||
|
||||
@Resource
|
||||
private ExecTaskManager execTaskManager;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ExecLogVO execCommand(ExecCommandRequest request) {
|
||||
@@ -186,7 +164,7 @@ public class ExecServiceImpl implements ExecService {
|
||||
public ExecLogVO reExecCommand(Long logId) {
|
||||
log.info("ExecService.reExecCommand start logId: {}", logId);
|
||||
// 获取执行记录
|
||||
ExecLogDO execLog = execLogDAO.selectById(logId);
|
||||
ExecLogDO execLog = execLogDAO.selectByIdSource(logId, ExecSourceEnum.BATCH.name());
|
||||
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
|
||||
// 获取执行主机
|
||||
List<ExecHostLogDO> hostLogs = execHostLogDAO.selectByLogId(logId);
|
||||
@@ -205,200 +183,6 @@ public class ExecServiceImpl implements ExecService {
|
||||
return this.execCommand(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void interruptExec(Long logId) {
|
||||
log.info("ExecService.interruptExec start logId: {}", logId);
|
||||
// 获取执行记录
|
||||
ExecLogDO execLog = execLogDAO.selectById(logId);
|
||||
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
|
||||
// 检查状态
|
||||
if (!ExecStatusEnum.of(execLog.getStatus()).isCloseable()) {
|
||||
return;
|
||||
}
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecService.interruptExec interrupted logId: {}", logId);
|
||||
// 中断
|
||||
task.interrupted();
|
||||
} else {
|
||||
log.info("ExecService.interruptExec updateStatus start logId: {}", logId);
|
||||
// 不存在则直接修改状态
|
||||
ExecLogDO updateExec = new ExecLogDO();
|
||||
updateExec.setId(logId);
|
||||
updateExec.setStatus(ExecStatusEnum.COMPLETED.name());
|
||||
updateExec.setFinishTime(new Date());
|
||||
int effect = execLogDAO.updateById(updateExec);
|
||||
// 更新主机状态
|
||||
ExecHostLogDO updateHost = new ExecHostLogDO();
|
||||
updateHost.setStatus(ExecHostStatusEnum.INTERRUPTED.name());
|
||||
updateHost.setFinishTime(new Date());
|
||||
LambdaQueryWrapper<ExecHostLogDO> updateHostWrapper = execHostLogDAO.lambda()
|
||||
.eq(ExecHostLogDO::getLogId, logId)
|
||||
.in(ExecHostLogDO::getStatus, ExecHostStatusEnum.CLOSEABLE_STATUS);
|
||||
effect += execHostLogDAO.update(updateHost, updateHostWrapper);
|
||||
log.info("ExecService.interruptExec updateStatus finish logId: {}, effect: {}", logId, effect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void interruptHostExec(Long hostLogId) {
|
||||
log.info("ExecService.interruptHostExec start hostLogId: {}", hostLogId);
|
||||
// 获取执行记录
|
||||
ExecHostLogDO hostLog = execHostLogDAO.selectById(hostLogId);
|
||||
Valid.notNull(hostLog, ErrorMessage.DATA_ABSENT);
|
||||
Long logId = hostLog.getLogId();
|
||||
// 添加日志参数
|
||||
OperatorLogs.add(OperatorLogs.LOG_ID, logId);
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, hostLog.getHostName());
|
||||
// 检查状态
|
||||
if (!ExecHostStatusEnum.of(hostLog.getStatus()).isCloseable()) {
|
||||
return;
|
||||
}
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecService.interruptHostExec interrupted logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
IExecCommandHandler handler = task.getHandlers()
|
||||
.stream()
|
||||
.filter(s -> s.getHostId().equals(hostLog.getHostId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
// 中断
|
||||
if (handler != null) {
|
||||
handler.interrupted();
|
||||
}
|
||||
} else {
|
||||
log.info("ExecService.interruptHostExec updateStatus start logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
// 不存在则直接修改状态
|
||||
ExecHostLogDO updateHost = new ExecHostLogDO();
|
||||
updateHost.setId(hostLogId);
|
||||
updateHost.setStatus(ExecHostStatusEnum.INTERRUPTED.name());
|
||||
updateHost.setFinishTime(new Date());
|
||||
int effect = execHostLogDAO.updateById(updateHost);
|
||||
// 查询执行状态
|
||||
ExecLogDO execLog = execLogDAO.selectById(logId);
|
||||
if (ExecStatusEnum.of(execLog.getStatus()).isCloseable()) {
|
||||
// 状态可修改则需要检查其他主机任务是否已经完成
|
||||
Long closeableCount = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.eq(ExecHostLogDO::getLogId, logId)
|
||||
.in(ExecHostLogDO::getStatus, ExecHostStatusEnum.CLOSEABLE_STATUS)
|
||||
.then()
|
||||
.count();
|
||||
if (closeableCount == 0) {
|
||||
// 修改任务状态
|
||||
ExecLogDO updateExec = new ExecLogDO();
|
||||
updateExec.setId(logId);
|
||||
updateExec.setStatus(ExecStatusEnum.COMPLETED.name());
|
||||
updateExec.setFinishTime(new Date());
|
||||
effect += execLogDAO.updateById(updateExec);
|
||||
}
|
||||
}
|
||||
log.info("ExecService.interruptHostExec updateStatus finish logId: {}, hostLogId: {}, effect: {}", logId, hostLogId, effect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExecLogTailToken(ExecLogTailRequest request) {
|
||||
Long execId = request.getExecId();
|
||||
List<Long> hostExecIdList = request.getHostExecIdList();
|
||||
log.info("ExecService.getExecLogTailToken start execId: {}, hostExecIdList: {}", execId, hostExecIdList);
|
||||
// 查询执行日志
|
||||
ExecLogDO execLog = execLogDAO.selectById(execId);
|
||||
Valid.notNull(execLog, ErrorMessage.LOG_ABSENT);
|
||||
// 查询主机日志
|
||||
List<ExecHostLogDO> hostLogs;
|
||||
if (hostExecIdList == null) {
|
||||
hostLogs = execHostLogDAO.selectByLogId(execId);
|
||||
} else {
|
||||
hostLogs = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.eq(ExecHostLogDO::getLogId, execId)
|
||||
.in(ExecHostLogDO::getId, hostExecIdList)
|
||||
.then()
|
||||
.list();
|
||||
}
|
||||
Valid.notEmpty(hostLogs, ErrorMessage.LOG_ABSENT);
|
||||
// 获取编码集
|
||||
List<Long> hostIdList = hostLogs.stream()
|
||||
.map(ExecHostLogDO::getHostId)
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, HostConfigVO> configMap = hostConfigService.getHostConfigList(hostIdList, HostConfigTypeEnum.SSH.getType())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(HostConfigVO::getId, Function.identity()));
|
||||
// 生成缓存
|
||||
String token = UUIds.random19();
|
||||
String cacheKey = ExecCacheKeyDefine.EXEC_TAIL.format(token);
|
||||
ExecLogTailDTO cache = ExecLogTailDTO.builder()
|
||||
.token(token)
|
||||
.id(execId)
|
||||
.userId(SecurityUtils.getLoginUserId())
|
||||
.hosts(hostLogs.stream()
|
||||
.map(s -> ExecHostLogTailDTO.builder()
|
||||
.id(s.getId())
|
||||
.hostId(s.getHostId())
|
||||
.path(s.getLogPath())
|
||||
.charset(Optional.ofNullable(configMap.get(s.getHostId()))
|
||||
.map(HostConfigVO::getConfig)
|
||||
.map(c -> c.get(FieldConst.CHARSET))
|
||||
.map(Objects1::toString)
|
||||
.orElse(Const.UTF_8))
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
// 设置缓存
|
||||
RedisStrings.setJson(cacheKey, ExecCacheKeyDefine.EXEC_TAIL, cache);
|
||||
log.info("ExecService.getExecLogTailToken finish token: {}, execId: {}, hostExecIdList: {}", token, execId, hostExecIdList);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecLogTailDTO getExecLogTailInfo(String token) {
|
||||
String cacheKey = ExecCacheKeyDefine.EXEC_TAIL.format(token);
|
||||
// 获取缓存
|
||||
ExecLogTailDTO tail = RedisStrings.getJson(cacheKey, ExecCacheKeyDefine.EXEC_TAIL);
|
||||
if (tail != null) {
|
||||
// 删除缓存
|
||||
RedisStrings.delete(cacheKey);
|
||||
}
|
||||
return tail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadLogFile(Long id, HttpServletResponse response) {
|
||||
log.info("ExecService.downloadLogFile id: {}", id);
|
||||
try {
|
||||
// 获取主机执行日志
|
||||
ExecHostLogDO hostLog = execHostLogDAO.selectById(id);
|
||||
Valid.notNull(hostLog, ErrorMessage.LOG_ABSENT);
|
||||
String logPath = hostLog.getLogPath();
|
||||
Valid.notNull(logPath, ErrorMessage.LOG_ABSENT);
|
||||
// 设置日志参数
|
||||
OperatorLogs.add(OperatorLogs.LOG_ID, hostLog.getLogId());
|
||||
OperatorLogs.add(OperatorLogs.HOST_ID, hostLog.getHostId());
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, hostLog.getHostName());
|
||||
// 获取日志
|
||||
InputStream in = logsFileClient.getContentInputStream(logPath);
|
||||
// 返回
|
||||
Servlets.transfer(response, in, Files1.getFileName(logPath));
|
||||
} catch (Exception e) {
|
||||
log.error("ExecService.downloadLogFile error id: {}", id, e);
|
||||
String errorMessage = ErrorMessage.FILE_READ_ERROR;
|
||||
if (e instanceof InvalidArgumentException) {
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
// 响应错误信息
|
||||
try {
|
||||
Servlets.transfer(response, Strings.bytes(errorMessage), Const.ERROR_LOG);
|
||||
} catch (Exception ex) {
|
||||
log.error("ExecService.downloadLogFile transfer-error id: {}", id, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行命令
|
||||
*
|
||||
@@ -26,7 +26,7 @@ import com.orion.ops.module.asset.handler.host.exec.job.ExecCommandJob;
|
||||
import com.orion.ops.module.asset.service.AssetAuthorizedDataService;
|
||||
import com.orion.ops.module.asset.service.ExecJobHostService;
|
||||
import com.orion.ops.module.asset.service.ExecJobService;
|
||||
import com.orion.ops.module.asset.service.ExecService;
|
||||
import com.orion.ops.module.asset.service.ExecCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -62,7 +62,7 @@ public class ExecJobServiceImpl implements ExecJobService {
|
||||
private ExecJobHostService execJobHostService;
|
||||
|
||||
@Resource
|
||||
private ExecService execService;
|
||||
private ExecCommandService execCommandService;
|
||||
|
||||
@Resource
|
||||
private AssetAuthorizedDataService assetAuthorizedDataService;
|
||||
@@ -271,7 +271,7 @@ public class ExecJobServiceImpl implements ExecJobService {
|
||||
.parameterSchema(job.getParameterSchema())
|
||||
.hostIdList(hostIdList)
|
||||
.build();
|
||||
ExecLogVO execResult = execService.execCommandWithSource(exec);
|
||||
ExecLogVO execResult = execCommandService.execCommandWithSource(exec);
|
||||
// 更新最近执行的任务id
|
||||
ExecJobDO updateRecent = new ExecJobDO();
|
||||
updateRecent.setId(id);
|
||||
|
||||
@@ -3,33 +3,55 @@ package com.orion.ops.module.asset.service.impl;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.lang.exception.argument.InvalidArgumentException;
|
||||
import com.orion.lang.id.UUIds;
|
||||
import com.orion.lang.utils.Arrays1;
|
||||
import com.orion.lang.utils.Objects1;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.constant.FieldConst;
|
||||
import com.orion.ops.framework.common.file.FileClient;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisStrings;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.ExecHostLogConvert;
|
||||
import com.orion.ops.module.asset.convert.ExecLogConvert;
|
||||
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
||||
import com.orion.ops.module.asset.dao.ExecLogDAO;
|
||||
import com.orion.ops.module.asset.define.cache.ExecCacheKeyDefine;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecLogDO;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecHostLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.dto.ExecLogTailDTO;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecLogTailRequest;
|
||||
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.entity.vo.HostConfigVO;
|
||||
import com.orion.ops.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.ops.module.asset.enums.ExecStatusEnum;
|
||||
import com.orion.ops.module.asset.enums.HostConfigTypeEnum;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.handler.IExecCommandHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.handler.IExecTaskHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.manager.ExecTaskManager;
|
||||
import com.orion.ops.module.asset.service.ExecHostLogService;
|
||||
import com.orion.ops.module.asset.service.ExecLogService;
|
||||
import com.orion.ops.module.asset.service.HostConfigService;
|
||||
import com.orion.web.servlet.web.Servlets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -55,6 +77,12 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Resource
|
||||
private ExecTaskManager execTaskManager;
|
||||
|
||||
@Resource
|
||||
private HostConfigService hostConfigService;
|
||||
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
@Override
|
||||
public DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request) {
|
||||
// 条件
|
||||
@@ -68,12 +96,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Override
|
||||
public ExecLogVO getExecLog(Long id, String source) {
|
||||
// 查询执行日志
|
||||
ExecLogDO row = execLogDAO.of()
|
||||
.createValidateWrapper()
|
||||
.eq(ExecLogDO::getId, id)
|
||||
.eq(ExecLogDO::getSource, source)
|
||||
.then()
|
||||
.getOne();
|
||||
ExecLogDO row = execLogDAO.selectByIdSource(id, source);
|
||||
Valid.notNull(row, ErrorMessage.LOG_ABSENT);
|
||||
// 查询执行主机
|
||||
List<ExecHostLogDO> hosts = execHostLogDAO.selectByLogId(id);
|
||||
@@ -113,7 +136,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecLogStatusVO getExecLogStatus(List<Long> idList) {
|
||||
public ExecLogStatusVO getExecLogStatus(List<Long> idList, String source) {
|
||||
// 查询执行状态
|
||||
List<ExecLogVO> logList = execLogDAO.of()
|
||||
.createWrapper()
|
||||
@@ -122,6 +145,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
ExecLogDO::getStartTime,
|
||||
ExecLogDO::getFinishTime)
|
||||
.in(ExecLogDO::getId, idList)
|
||||
.eq(ExecLogDO::getSource, source)
|
||||
.then()
|
||||
.list(ExecLogConvert.MAPPER::to);
|
||||
// 查询主机状态
|
||||
@@ -144,17 +168,12 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long queryExecLogCount(ExecLogQueryRequest request) {
|
||||
return execLogDAO.selectCount(this.buildQueryWrapper(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer deleteExecLogById(Long id) {
|
||||
public Integer deleteExecLogById(Long id, String source) {
|
||||
log.info("ExecLogService-deleteExecLogById id: {}", id);
|
||||
// 检查数据是否存在
|
||||
ExecLogDO record = execLogDAO.selectById(id);
|
||||
ExecLogDO record = execLogDAO.selectByIdSource(id, source);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(Lists.singleton(id));
|
||||
@@ -170,8 +189,16 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer deleteExecLogByIdList(List<Long> idList) {
|
||||
public Integer deleteExecLogByIdList(List<Long> idList, String source) {
|
||||
log.info("ExecLogService-deleteExecLogByIdList idList: {}", idList);
|
||||
int count = execLogDAO.of()
|
||||
.createWrapper()
|
||||
.in(ExecLogDO::getId, idList)
|
||||
.eq(ExecLogDO::getSource, source)
|
||||
.then()
|
||||
.count()
|
||||
.intValue();
|
||||
Valid.isTrue(idList.size() == count, ErrorMessage.DATA_MODIFIED);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(idList);
|
||||
// 删除执行日志
|
||||
@@ -184,6 +211,11 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long queryExecLogCount(ExecLogQueryRequest request) {
|
||||
return execLogDAO.selectCount(this.buildQueryWrapper(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer clearExecLog(ExecLogQueryRequest request) {
|
||||
@@ -210,6 +242,204 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void interruptExec(Long logId, String source) {
|
||||
log.info("ExecLogService.interruptExec start logId: {}, source: {}", logId, source);
|
||||
// 获取执行记录
|
||||
ExecLogDO execLog = execLogDAO.selectByIdSource(logId, source);
|
||||
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
|
||||
// 检查状态
|
||||
if (!ExecStatusEnum.of(execLog.getStatus()).isCloseable()) {
|
||||
return;
|
||||
}
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecLogService.interruptExec interrupted logId: {}", logId);
|
||||
// 中断
|
||||
task.interrupted();
|
||||
} else {
|
||||
log.info("ExecLogService.interruptExec updateStatus start logId: {}", logId);
|
||||
// 不存在则直接修改状态
|
||||
ExecLogDO updateExec = new ExecLogDO();
|
||||
updateExec.setId(logId);
|
||||
updateExec.setStatus(ExecStatusEnum.COMPLETED.name());
|
||||
updateExec.setFinishTime(new Date());
|
||||
int effect = execLogDAO.updateById(updateExec);
|
||||
// 更新主机状态
|
||||
ExecHostLogDO updateHost = new ExecHostLogDO();
|
||||
updateHost.setStatus(ExecHostStatusEnum.INTERRUPTED.name());
|
||||
updateHost.setFinishTime(new Date());
|
||||
LambdaQueryWrapper<ExecHostLogDO> updateHostWrapper = execHostLogDAO.lambda()
|
||||
.eq(ExecHostLogDO::getLogId, logId)
|
||||
.in(ExecHostLogDO::getStatus, ExecHostStatusEnum.CLOSEABLE_STATUS);
|
||||
effect += execHostLogDAO.update(updateHost, updateHostWrapper);
|
||||
log.info("ExecLogService.interruptExec updateStatus finish logId: {}, effect: {}", logId, effect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void interruptHostExec(Long hostLogId, String source) {
|
||||
log.info("ExecLogService.interruptHostExec start hostLogId: {}, source: {}", hostLogId, source);
|
||||
// 获取执行记录
|
||||
ExecHostLogDO hostLog = execHostLogDAO.selectById(hostLogId);
|
||||
Valid.notNull(hostLog, ErrorMessage.DATA_ABSENT);
|
||||
Long logId = hostLog.getLogId();
|
||||
ExecLogDO execLog = execLogDAO.selectByIdSource(logId, source);
|
||||
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
|
||||
// 添加日志参数
|
||||
OperatorLogs.add(OperatorLogs.LOG_ID, logId);
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, hostLog.getHostName());
|
||||
// 检查状态
|
||||
if (!ExecHostStatusEnum.of(hostLog.getStatus()).isCloseable()) {
|
||||
return;
|
||||
}
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecLogService.interruptHostExec interrupted logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
IExecCommandHandler handler = task.getHandlers()
|
||||
.stream()
|
||||
.filter(s -> s.getHostId().equals(hostLog.getHostId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
// 中断
|
||||
if (handler != null) {
|
||||
handler.interrupted();
|
||||
}
|
||||
} else {
|
||||
log.info("ExecLogService.interruptHostExec updateStatus start logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
// 不存在则直接修改状态
|
||||
ExecHostLogDO updateHost = new ExecHostLogDO();
|
||||
updateHost.setId(hostLogId);
|
||||
updateHost.setStatus(ExecHostStatusEnum.INTERRUPTED.name());
|
||||
updateHost.setFinishTime(new Date());
|
||||
int effect = execHostLogDAO.updateById(updateHost);
|
||||
// 检查是否可关闭
|
||||
if (ExecStatusEnum.of(execLog.getStatus()).isCloseable()) {
|
||||
// 状态可修改则需要检查其他主机任务是否已经完成
|
||||
Long closeableCount = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.eq(ExecHostLogDO::getLogId, logId)
|
||||
.in(ExecHostLogDO::getStatus, ExecHostStatusEnum.CLOSEABLE_STATUS)
|
||||
.then()
|
||||
.count();
|
||||
if (closeableCount == 0) {
|
||||
// 修改任务状态
|
||||
ExecLogDO updateExec = new ExecLogDO();
|
||||
updateExec.setId(logId);
|
||||
updateExec.setStatus(ExecStatusEnum.COMPLETED.name());
|
||||
updateExec.setFinishTime(new Date());
|
||||
effect += execLogDAO.updateById(updateExec);
|
||||
}
|
||||
}
|
||||
log.info("ExecLogService.interruptHostExec updateStatus finish logId: {}, hostLogId: {}, effect: {}", logId, hostLogId, effect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExecLogTailToken(ExecLogTailRequest request) {
|
||||
String source = request.getSource();
|
||||
Long execId = request.getExecId();
|
||||
List<Long> hostExecIdList = request.getHostExecIdList();
|
||||
log.info("ExecLogService.getExecLogTailToken start execId: {}, hostExecIdList: {}", execId, hostExecIdList);
|
||||
// 查询执行日志
|
||||
ExecLogDO execLog = execLogDAO.selectByIdSource(execId, source);
|
||||
Valid.notNull(execLog, ErrorMessage.LOG_ABSENT);
|
||||
// 查询主机日志
|
||||
List<ExecHostLogDO> hostLogs;
|
||||
if (hostExecIdList == null) {
|
||||
hostLogs = execHostLogDAO.selectByLogId(execId);
|
||||
} else {
|
||||
hostLogs = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.eq(ExecHostLogDO::getLogId, execId)
|
||||
.in(ExecHostLogDO::getId, hostExecIdList)
|
||||
.then()
|
||||
.list();
|
||||
}
|
||||
Valid.notEmpty(hostLogs, ErrorMessage.LOG_ABSENT);
|
||||
// 获取编码集
|
||||
List<Long> hostIdList = hostLogs.stream()
|
||||
.map(ExecHostLogDO::getHostId)
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, HostConfigVO> configMap = hostConfigService.getHostConfigList(hostIdList, HostConfigTypeEnum.SSH.getType())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(HostConfigVO::getId, Function.identity()));
|
||||
// 生成缓存
|
||||
String token = UUIds.random19();
|
||||
String cacheKey = ExecCacheKeyDefine.EXEC_TAIL.format(token);
|
||||
ExecLogTailDTO cache = ExecLogTailDTO.builder()
|
||||
.token(token)
|
||||
.id(execId)
|
||||
.userId(SecurityUtils.getLoginUserId())
|
||||
.hosts(hostLogs.stream()
|
||||
.map(s -> ExecHostLogTailDTO.builder()
|
||||
.id(s.getId())
|
||||
.hostId(s.getHostId())
|
||||
.path(s.getLogPath())
|
||||
.charset(Optional.ofNullable(configMap.get(s.getHostId()))
|
||||
.map(HostConfigVO::getConfig)
|
||||
.map(c -> c.get(FieldConst.CHARSET))
|
||||
.map(Objects1::toString)
|
||||
.orElse(Const.UTF_8))
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
// 设置缓存
|
||||
RedisStrings.setJson(cacheKey, ExecCacheKeyDefine.EXEC_TAIL, cache);
|
||||
log.info("ExecLogService.getExecLogTailToken finish token: {}, execId: {}, hostExecIdList: {}", token, execId, hostExecIdList);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecLogTailDTO getExecLogTailInfo(String token) {
|
||||
String cacheKey = ExecCacheKeyDefine.EXEC_TAIL.format(token);
|
||||
// 获取缓存
|
||||
ExecLogTailDTO tail = RedisStrings.getJson(cacheKey, ExecCacheKeyDefine.EXEC_TAIL);
|
||||
if (tail != null) {
|
||||
// 删除缓存
|
||||
RedisStrings.delete(cacheKey);
|
||||
}
|
||||
return tail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadLogFile(Long id, String source, HttpServletResponse response) {
|
||||
log.info("ExecLogService.downloadLogFile id: {}, source: {}", id, source);
|
||||
try {
|
||||
// 获取主机执行日志
|
||||
ExecHostLogDO hostLog = execHostLogDAO.selectById(id);
|
||||
Valid.notNull(hostLog, ErrorMessage.LOG_ABSENT);
|
||||
String logPath = hostLog.getLogPath();
|
||||
Valid.notNull(logPath, ErrorMessage.LOG_ABSENT);
|
||||
ExecLogDO execLog = execLogDAO.selectByIdSource(hostLog.getLogId(), source);
|
||||
Valid.notNull(execLog, ErrorMessage.LOG_ABSENT);
|
||||
// 设置日志参数
|
||||
OperatorLogs.add(OperatorLogs.LOG_ID, hostLog.getLogId());
|
||||
OperatorLogs.add(OperatorLogs.HOST_ID, hostLog.getHostId());
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, hostLog.getHostName());
|
||||
// 获取日志
|
||||
InputStream in = logsFileClient.getContentInputStream(logPath);
|
||||
// 返回
|
||||
Servlets.transfer(response, in, Files1.getFileName(logPath));
|
||||
} catch (Exception e) {
|
||||
log.error("ExecLogService.downloadLogFile error id: {}", id, e);
|
||||
String errorMessage = ErrorMessage.FILE_READ_ERROR;
|
||||
if (e instanceof InvalidArgumentException) {
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
// 响应错误信息
|
||||
try {
|
||||
Servlets.transfer(response, Strings.bytes(errorMessage), Const.ERROR_LOG);
|
||||
} catch (Exception ex) {
|
||||
log.error("ExecLogService.downloadLogFile transfer-error id: {}", id, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询 wrapper
|
||||
*
|
||||
|
||||
169
orion-ops-ui/src/api/exec/exec-command-log.ts
Normal file
169
orion-ops-ui/src/api/exec/exec-command-log.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
import type { DataGrid, Pagination } from '@/types/global';
|
||||
import type { TableData } from '@arco-design/web-vue/es/table/interface';
|
||||
import axios from 'axios';
|
||||
import qs from 'query-string';
|
||||
|
||||
/**
|
||||
* 执行记录查询请求
|
||||
*/
|
||||
export interface ExecCommandLogQueryRequest extends Pagination {
|
||||
id?: number;
|
||||
userId?: number;
|
||||
description?: string;
|
||||
command?: string;
|
||||
status?: string;
|
||||
startTimeRange?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行记录查询响应
|
||||
*/
|
||||
export interface ExecCommandLogQueryResponse extends TableData, ExecCommandLogQueryExtraResponse {
|
||||
id: number;
|
||||
userId: number;
|
||||
username: string;
|
||||
description: string;
|
||||
command: string;
|
||||
parameterSchema: string;
|
||||
timeout: number;
|
||||
status: string;
|
||||
startTime: number;
|
||||
finishTime: number;
|
||||
hostIdList: Array<number>;
|
||||
hosts: Array<ExecCommandHostLogQueryResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行记录查询响应 拓展
|
||||
*/
|
||||
export interface ExecCommandLogQueryExtraResponse {
|
||||
hosts: Array<ExecCommandHostLogQueryResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主机执行记录查询响应
|
||||
*/
|
||||
export interface ExecCommandHostLogQueryResponse extends TableData {
|
||||
id: number;
|
||||
logId: number;
|
||||
hostId: number;
|
||||
hostName: string;
|
||||
hostAddress: string;
|
||||
status: string;
|
||||
command: string;
|
||||
parameter: string;
|
||||
exitStatus: number;
|
||||
errorMessage: string;
|
||||
startTime: number;
|
||||
finishTime: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行状态查询响应
|
||||
*/
|
||||
export interface ExecCommandLogStatusResponse {
|
||||
logList: Array<ExecCommandLogQueryResponse>;
|
||||
hostList: Array<ExecCommandHostLogQueryResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断命令请求
|
||||
*/
|
||||
export interface ExecCommandLogTailRequest {
|
||||
execId?: number;
|
||||
hostExecIdList?: Array<number>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询执行记录
|
||||
*/
|
||||
export function getExecCommandLogPage(request: ExecCommandLogQueryRequest) {
|
||||
return axios.post<DataGrid<ExecCommandLogQueryResponse>>('/asset/exec-command-log/query', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询执行记录
|
||||
*/
|
||||
export function getExecCommandLog(id: number) {
|
||||
return axios.get<ExecCommandLogQueryResponse>('/asset/exec-command-log/get', { params: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主机执行记录
|
||||
*/
|
||||
export function getExecCommandHostLogList(logId: number) {
|
||||
return axios.get<Array<ExecCommandHostLogQueryResponse>>('/asset/exec-command-log/host-list', { params: { logId } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询命令执行状态
|
||||
*/
|
||||
export function getExecCommandLogStatus(idList: Array<number>) {
|
||||
return axios.get<ExecCommandLogStatusResponse>('/asset/exec-command-log/status', {
|
||||
params: { idList },
|
||||
paramsSerializer: params => {
|
||||
return qs.stringify(params, { arrayFormat: 'comma' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询历史执行记录
|
||||
*/
|
||||
export function getExecCommandLogHistory(limit: number) {
|
||||
return axios.get<Array<ExecCommandLogQueryResponse>>('/asset/exec-command-log/history', { params: { page: 1, limit } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除执行记录
|
||||
*/
|
||||
export function deleteExecCommandLog(id: number) {
|
||||
return axios.delete('/asset/exec-command-log/delete', { params: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除执行记录
|
||||
*/
|
||||
export function batchDeleteExecCommandLog(idList: Array<number>) {
|
||||
return axios.delete('/asset/exec-command-log/batch-delete', {
|
||||
params: { idList },
|
||||
paramsSerializer: params => {
|
||||
return qs.stringify(params, { arrayFormat: 'comma' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除主机执行记录
|
||||
*/
|
||||
export function deleteExecCommandHostLog(id: number) {
|
||||
return axios.delete('/asset/exec-command-log/delete-host', { params: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询操作日志数量
|
||||
*/
|
||||
export function getExecCommandLogCount(request: ExecCommandLogQueryRequest) {
|
||||
return axios.post<number>('/asset/exec-command-log/query-count', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空操作日志
|
||||
*/
|
||||
export function clearExecCommandLog(request: ExecCommandLogQueryRequest) {
|
||||
return axios.post<number>('/asset/exec-command-log/clear', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看执行日志
|
||||
*/
|
||||
export function getExecCommandLogTailToken(request: ExecCommandLogTailRequest) {
|
||||
return axios.post<string>('/asset/exec-command-log/tail', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载执行日志文件
|
||||
*/
|
||||
export function downloadExecCommandLogFile(id: number) {
|
||||
return axios.get('/asset/exec-command-log/download', { unwrap: true, params: { id } });
|
||||
}
|
||||
50
orion-ops-ui/src/api/exec/exec-command.ts
Normal file
50
orion-ops-ui/src/api/exec/exec-command.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { ExecLogQueryResponse } from './exec-log';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* 执行命令请求
|
||||
*/
|
||||
export interface ExecCommandRequest {
|
||||
logId?: number;
|
||||
description?: string;
|
||||
timeout?: number;
|
||||
command?: string;
|
||||
parameterSchema?: string;
|
||||
hostIdList?: Array<number>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断命令请求
|
||||
*/
|
||||
export interface ExecCommandInterruptRequest {
|
||||
logId?: number;
|
||||
hostLogId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行命令
|
||||
*/
|
||||
export function batchExecCommand(request: ExecCommandRequest) {
|
||||
return axios.post<ExecLogQueryResponse>('/asset/exec-command/exec', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新执行命令
|
||||
*/
|
||||
export function reExecCommand(request: ExecCommandRequest) {
|
||||
return axios.post<ExecLogQueryResponse>('/asset/exec-command/re-exec', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断执行命令
|
||||
*/
|
||||
export function interruptExecCommand(request: ExecCommandInterruptRequest) {
|
||||
return axios.put('/asset/exec-command/interrupt', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断执行主机命令
|
||||
*/
|
||||
export function interruptHostExecCommand(request: ExecCommandInterruptRequest) {
|
||||
return axios.put('/asset/exec-command/interrupt-host', request);
|
||||
}
|
||||
@@ -13,9 +13,9 @@ const EXEC: AppRouteRecordRaw[] = [
|
||||
component: () => import('@/views/exec/exec-command/index.vue'),
|
||||
},
|
||||
{
|
||||
name: 'execLog',
|
||||
path: '/exec-log',
|
||||
component: () => import('@/views/exec/exec-log/index.vue'),
|
||||
name: 'execCommandLog',
|
||||
path: '/exec-command-log',
|
||||
component: () => import('@/views/exec/exec-command-log/index.vue'),
|
||||
},
|
||||
{
|
||||
name: 'execTemplate',
|
||||
|
||||
Reference in New Issue
Block a user