fix: ASW-146 修复 job 执行时未修改 environment 状态和未添加session记录
This commit is contained in:
@@ -6,6 +6,7 @@ import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Constants {
|
||||
|
||||
@@ -104,6 +105,11 @@ public class Constants {
|
||||
public static final Map<String, WebSocketSession> ENV_TERMINAL_WEBSOCKET_SESSION = T.MapUtil.newHashMap();
|
||||
|
||||
|
||||
public static final ConcurrentHashMap<String, Thread> RUNNING_JOB_THREAD = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ConcurrentHashMap<String, Thread> RESULT_JOB_THREAD = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Android package type
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ public enum RCode {
|
||||
SYS_ROLE_BUILT_IN(100017, "Built-in role are not allowed to delete or update"),
|
||||
SYS_ROLE_NOT_DELETE(100018, "Used role cannot be deleted"),
|
||||
SYS_USER_OLDPWD_INCORRECT(100019, "Incorrect old password. Please try again."),
|
||||
SYS_SYSTEM_USER_NOT_LOGIN(100020, "System user cannot login."),
|
||||
|
||||
|
||||
// Application
|
||||
|
||||
@@ -169,25 +169,7 @@ public class EnvironmentController {
|
||||
@DeleteMapping("/{envId}/session/{sessionId}")
|
||||
@Transactional
|
||||
public R removeSession(@PathVariable("envId") String envId, @PathVariable("sessionId") String sessionId, @RequestParam String workspaceId) {
|
||||
EnvironmentSessionEntity session = environmentSessionService.getById(sessionId);
|
||||
WebSocketSession novncSession = Constants.ENV_NOVNC_WEBSOCKET_SESSION.get(sessionId);
|
||||
WebSocketSession terminalSession = Constants.ENV_TERMINAL_WEBSOCKET_SESSION.get(sessionId);
|
||||
// 根据 session 找到 novncSession&terminalSession ,更新状态,设置结束时间
|
||||
session.setEndTimestamp(System.currentTimeMillis());
|
||||
session.setStatus(2);
|
||||
environmentSessionService.updateById(session);
|
||||
try {
|
||||
if (T.ObjectUtil.isNotEmpty(novncSession)) {
|
||||
Constants.ENV_NOVNC_WEBSOCKET_SESSION.remove(sessionId);
|
||||
novncSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected."));
|
||||
}
|
||||
if (T.ObjectUtil.isNotEmpty(terminalSession)) {
|
||||
Constants.ENV_TERMINAL_WEBSOCKET_SESSION.remove(sessionId);
|
||||
terminalSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected."));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e, "RemoveSession send exit prompt error sessionId: {}", sessionId);
|
||||
}
|
||||
environmentService.removeSession(sessionId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,4 +22,6 @@ public interface IEnvironmentService extends IService<EnvironmentEntity>{
|
||||
EnvironmentEntity saveEnv(EnvironmentEntity entity);
|
||||
|
||||
EnvironmentEntity updateEnv(EnvironmentEntity entity);
|
||||
|
||||
void removeSession(String sessionId);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import net.geedge.asw.common.config.Query;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.Constants;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.attribute.entity.AttributeEntity;
|
||||
@@ -24,7 +25,10 @@ import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
@@ -202,4 +206,27 @@ public class EnvironmentServiceImpl extends ServiceImpl<EnvironmentDao, Environm
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSession(String sessionId) {
|
||||
EnvironmentSessionEntity session = environmentSessionService.getById(sessionId);
|
||||
WebSocketSession novncSession = Constants.ENV_NOVNC_WEBSOCKET_SESSION.get(sessionId);
|
||||
WebSocketSession terminalSession = Constants.ENV_TERMINAL_WEBSOCKET_SESSION.get(sessionId);
|
||||
// 根据 session 找到 novncSession&terminalSession ,更新状态,设置结束时间
|
||||
session.setEndTimestamp(System.currentTimeMillis());
|
||||
session.setStatus(2);
|
||||
environmentSessionService.updateById(session);
|
||||
try {
|
||||
if (T.ObjectUtil.isNotEmpty(novncSession)) {
|
||||
Constants.ENV_NOVNC_WEBSOCKET_SESSION.remove(sessionId);
|
||||
novncSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected."));
|
||||
}
|
||||
if (T.ObjectUtil.isNotEmpty(terminalSession)) {
|
||||
Constants.ENV_TERMINAL_WEBSOCKET_SESSION.remove(sessionId);
|
||||
terminalSession.close(CloseStatus.NORMAL.withReason("Administrator disconnected."));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e, "RemoveSession send exit prompt error sessionId: {}", sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentEntity;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
|
||||
@@ -56,4 +57,9 @@ public class JobEntity {
|
||||
@TableField(exist = false)
|
||||
private WorkspaceEntity workspace;
|
||||
|
||||
@TableField(exist = false)
|
||||
private EnvironmentSessionEntity session;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
package net.geedge.asw.module.runner.job;
|
||||
|
||||
import cn.hutool.http.Header;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import net.geedge.asw.common.util.Constants;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||
import net.geedge.asw.module.app.service.IPackageService;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentEntity;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentService;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentSessionService;
|
||||
import net.geedge.asw.module.runner.entity.JobEntity;
|
||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||
import net.geedge.asw.module.runner.service.IJobService;
|
||||
@@ -27,12 +27,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@@ -54,15 +53,11 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
@Autowired
|
||||
private IPackageService packageService;
|
||||
|
||||
// 用于追踪虚拟线程,每个 Job 只对应一个虚拟线程
|
||||
private List runningJobThreads = T.ListUtil.list(false);
|
||||
|
||||
private List resultJobThreads = T.ListUtil.list(false);
|
||||
|
||||
@Autowired
|
||||
private IEnvironmentSessionService environmentSessionService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||
|
||||
Thread.currentThread().setName("JobPlaybookExecResultChecker");
|
||||
|
||||
log.info("[JobPlaybookExecResultChecker] [begin]");
|
||||
@@ -109,26 +104,15 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
String status = data.getStr("status");
|
||||
|
||||
switch (status){
|
||||
switch (status) {
|
||||
case "running":
|
||||
if (!runningJobThreads.contains(id)){
|
||||
runningJobThreads.add(id);
|
||||
startJobVirtualThread(job, environment);
|
||||
}
|
||||
Constants.RUNNING_JOB_THREAD.computeIfAbsent(id, jobId -> startGetJobLogThread(job, environment));
|
||||
break;
|
||||
case "error":
|
||||
updateJobStatus(job, RunnerConstant.JobStatus.FAILED.getValue());
|
||||
if (!resultJobThreads.contains(id)){
|
||||
resultJobThreads.add(id);
|
||||
getJobResult(job, environment);
|
||||
}
|
||||
Constants.RESULT_JOB_THREAD.computeIfAbsent(id, jobId -> startGetJobResultThread(job, environment, RunnerConstant.JobStatus.FAILED.getValue()));
|
||||
break;
|
||||
case "done":
|
||||
updateJobStatus(job, RunnerConstant.JobStatus.PASSED.getValue());
|
||||
if (!resultJobThreads.contains(id)){
|
||||
resultJobThreads.add(id);
|
||||
getJobResult(job, environment);
|
||||
}
|
||||
Constants.RESULT_JOB_THREAD.computeIfAbsent(id, jobId -> startGetJobResultThread(job, environment, RunnerConstant.JobStatus.PASSED.getValue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -137,24 +121,25 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
}
|
||||
}
|
||||
|
||||
private void startJobVirtualThread(JobEntity job, EnvironmentEntity environment) {
|
||||
T.ThreadUtil.execAsync(() -> {
|
||||
private Thread startGetJobLogThread(JobEntity job, EnvironmentEntity environment) {
|
||||
Thread thread = Thread.ofVirtual().start(() -> {
|
||||
log.info("[playbookExecResultChecker] [startGetJobLogThread] [begin] [job id: {}]", job.getId());
|
||||
try {
|
||||
while (true) {
|
||||
if (isJobInRunningStatus(job)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[playbookExecResultChecker] [Job status updated] [stopJobVirtualThread ] [job id: {}]", job.getId());
|
||||
}
|
||||
runningJobThreads.remove(job.getId());
|
||||
Constants.RUNNING_JOB_THREAD.remove(job.getId());
|
||||
log.info("[playbookExecResultChecker] [startGetJobLogThread] [finshed ] [job id: {}]", job.getId());
|
||||
break;
|
||||
}
|
||||
performJobLogic(job, environment);
|
||||
Thread.sleep(2000); // 每 2 秒执行一次
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Constants.RUNNING_JOB_THREAD.remove(job.getId());
|
||||
Thread.currentThread().interrupt(); // 恢复中断状态
|
||||
}
|
||||
});
|
||||
return thread;
|
||||
}
|
||||
|
||||
// 检查 Job 的状态是否为 running
|
||||
@@ -165,13 +150,14 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
|
||||
/**
|
||||
* 获取 playbook 执行日志
|
||||
*
|
||||
* @param job
|
||||
* @param environment
|
||||
*/
|
||||
private void performJobLogic(JobEntity job, EnvironmentEntity environment) {
|
||||
File logFile = T.FileUtil.file(job.getLogPath());
|
||||
Integer offset = 0;
|
||||
if (logFile.exists()){
|
||||
if (logFile.exists()) {
|
||||
offset = T.FileUtil.readBytes(logFile).length;
|
||||
}
|
||||
JSONObject paramJSONObject = environment.getParamJSONObject();
|
||||
@@ -192,32 +178,28 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
if (T.ObjectUtil.equal(RCode.SUCCESS.getCode(), jsonObject.getInt("code"))) {
|
||||
JSONObject data = jsonObject.getJSONObject("data");
|
||||
String content = data.getStr("content");
|
||||
content = T.StrUtil.nullToDefault(content, T.StrUtil.EMPTY);
|
||||
T.FileUtil.appendString(content, logFile, "UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PreDestroy
|
||||
public void shutdown() {
|
||||
runningJobThreads.clear();
|
||||
resultJobThreads.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get pcap log
|
||||
*
|
||||
* @param job
|
||||
* @param value job status: error and done
|
||||
* @param value job status: error and done
|
||||
* @param environment
|
||||
*/
|
||||
private void getJobResult(JobEntity job, EnvironmentEntity environment) {
|
||||
T.ThreadUtil.execAsync(() -> {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
private Thread startGetJobResultThread(JobEntity job, EnvironmentEntity environment, String status) {
|
||||
Thread thread = Thread.ofVirtual().start(() -> {
|
||||
File destination = null;
|
||||
File pcapDestination = null;
|
||||
InputStream inputStream = null;
|
||||
ZipFile zipFile = null;
|
||||
try {
|
||||
log.info("[playbookExecResultChecker] [startGetJobResultThread] [job status] [jod id: {}]", status, job.getId());
|
||||
JSONObject paramJSONObject = environment.getParamJSONObject();
|
||||
String url = paramJSONObject.getStr("url");
|
||||
String token = paramJSONObject.getStr("token");
|
||||
@@ -225,8 +207,7 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
request.header("Authorization", token);
|
||||
|
||||
HttpResponse response = request.execute();
|
||||
|
||||
log.info("[playbookExecResultChecker] [getJobResult] [jod id: {}] [request env api] [status: {}]", job.getId(), response.getStatus());
|
||||
log.info("[playbookExecResultChecker] [startGetJobResultThread] [request env playbook result api] [status: {}]", response.getStatus());
|
||||
|
||||
if (response.isOk()) {
|
||||
destination = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip"));
|
||||
@@ -236,6 +217,7 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
for (ZipEntry entry : list) {
|
||||
if (entry.getName().endsWith("pcap")) {
|
||||
PackageEntity packageEntity = packageService.getById(job.getPackageId());
|
||||
|
||||
// pcap name {package.name}-job-{jobId[0:8]}.pcap
|
||||
String fileName = T.StrUtil.concat(true, packageEntity.getName(), T.StrUtil.DASHED, "job", T.StrUtil.DASHED, T.StrUtil.sub(job.getId(), 0, 8), ".pcap");
|
||||
pcapDestination = T.FileUtil.file(Constants.TEMP_PATH, fileName);
|
||||
@@ -244,13 +226,8 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
Resource fileResource = new FileSystemResource(pcapDestination);
|
||||
// upload pcap file
|
||||
PcapEntity pcapEntity = pcapService.savePcap(fileResource, "", job.getWorkspaceId(), job.getCreateUserId());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[playbookExecResultChecker] [getJobResult] [job id: {}]: {}] [upload pcap: {}]", job.getId(), T.JSONUtil.toJsonStr(pcapEntity));
|
||||
}
|
||||
|
||||
log.info("[playbookExecResultChecker] [startGetJobResultThread] [upload pcap: {}] [job id: {}]: {}] ", T.JSONUtil.toJsonStr(pcapEntity), job.getId());
|
||||
job.setPcapId(pcapEntity.getId());
|
||||
jobService.updateById(job);
|
||||
} else {
|
||||
// log
|
||||
inputStream = T.ZipUtil.get(zipFile, entry.getName());
|
||||
@@ -259,23 +236,26 @@ public class JobPlaybookExecResultChecker extends QuartzJobBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
// update job status
|
||||
job.setStatus(status);
|
||||
job.setEndTimestamp(System.currentTimeMillis());
|
||||
jobService.updateById(job);
|
||||
|
||||
// remove session
|
||||
EnvironmentSessionEntity session = environmentSessionService.getOne(new LambdaQueryWrapper<EnvironmentSessionEntity>().eq(EnvironmentSessionEntity::getJobId, job.getId()));
|
||||
environmentService.removeSession(session.getId());
|
||||
log.info("[playbookExecResultChecker] [startGetJobResultThread] [finshed] [job id: {}]", job.getId());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[playbookExecResultChecker] [getJobResult] [error]", e);
|
||||
log.error("[playbookExecResultChecker] [startGetJobResultThread] [error]", e);
|
||||
} finally {
|
||||
T.IoUtil.close(zipFile);
|
||||
T.FileUtil.del(destination);
|
||||
T.FileUtil.del(pcapDestination);
|
||||
T.IoUtil.close(inputStream);
|
||||
resultJobThreads.remove(job.getId());
|
||||
Constants.RESULT_JOB_THREAD.remove(job.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateJobStatus(JobEntity job, String value) {
|
||||
log.info("[playbookExecResultChecker] [updateJobStatus] [jod id: {}] [status: {}]", job.getId(), value);
|
||||
job.setStatus(value);
|
||||
job.setEndTimestamp(System.currentTimeMillis());
|
||||
jobService.updateById(job);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||
import net.geedge.asw.module.app.service.IPackageService;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentEntity;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentService;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentSessionService;
|
||||
import net.geedge.asw.module.runner.entity.JobEntity;
|
||||
import net.geedge.asw.module.runner.entity.PlaybookEntity;
|
||||
import net.geedge.asw.module.runner.service.IJobService;
|
||||
@@ -48,6 +50,9 @@ public class JobPlaybookExecutor extends QuartzJobBean {
|
||||
@Autowired
|
||||
private IPlaybookService playbookService;
|
||||
|
||||
@Autowired
|
||||
private IEnvironmentSessionService environmentSessionService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) {
|
||||
Thread.currentThread().setName("JobPlaybookExecutor");
|
||||
@@ -67,17 +72,20 @@ public class JobPlaybookExecutor extends QuartzJobBean {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void playbookExecutor() {
|
||||
List<JobEntity> list = jobService.list(new LambdaQueryWrapper<JobEntity>().eq(JobEntity::getStatus, RunnerConstant.JobStatus.CREATED.getValue()));
|
||||
Map<String, List<JobEntity>> jobByEnvList = list.stream().collect(Collectors.groupingBy(JobEntity::getEnvId));
|
||||
List<JobEntity> createdList = jobService.list(new LambdaQueryWrapper<JobEntity>().eq(JobEntity::getStatus, RunnerConstant.JobStatus.CREATED.getValue()));
|
||||
Map<String, List<JobEntity>> jobByEnvList = createdList.stream().collect(Collectors.groupingBy(JobEntity::getEnvId));
|
||||
for (Map.Entry<String, List<JobEntity>> jobByEnv : jobByEnvList.entrySet()) {
|
||||
String envId = jobByEnv.getKey();
|
||||
List<JobEntity> jobList = jobByEnv.getValue();
|
||||
Thread.ofVirtual().start(() -> {
|
||||
T.ThreadUtil.execAsync(() -> {
|
||||
for (JobEntity job : jobList) {
|
||||
List<JobEntity> JobRunList = jobService.list(new LambdaQueryWrapper<JobEntity>().eq(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()).eq(JobEntity::getEnvId, envId));
|
||||
List<JobEntity> JobRunList = jobService.list(new LambdaQueryWrapper<JobEntity>()
|
||||
.eq(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue())
|
||||
.eq(JobEntity::getEnvId, envId));
|
||||
if (T.CollUtil.isNotEmpty(JobRunList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EnvironmentEntity environment = environmentService.getById(envId);
|
||||
if (!environment.getStatus().equals(1)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -86,40 +94,37 @@ public class JobPlaybookExecutor extends QuartzJobBean {
|
||||
continue;
|
||||
}
|
||||
|
||||
String playbookId = job.getPlaybookId();
|
||||
String packageId = job.getPackageId();
|
||||
PackageEntity packageEntity = packageService.getById(packageId);
|
||||
File packageFile = T.FileUtil.file(packageEntity.getPath());
|
||||
String packageName = packageEntity.getIdentifier();
|
||||
PlaybookEntity playbook = playbookService.getById(playbookId);
|
||||
File playbookFile = T.FileUtil.file(playbook.getPath());
|
||||
List<EnvironmentSessionEntity> sessionList = environmentSessionService.list(new LambdaQueryWrapper<EnvironmentSessionEntity>()
|
||||
.eq(EnvironmentSessionEntity::getStatus, "1")
|
||||
.eq(EnvironmentSessionEntity::getEnvId, envId));
|
||||
if (T.CollUtil.isNotEmpty(sessionList)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[playbookExecutor] [environment is in used] [jobId: {}] [envId: {}]", job.getId(), environment.getId());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
log.info("[playbookExecutor] [jobId: {}] [envId: {}] [playbookId: {}] [packageId: {}]", job.getId(), environment.getId(), playbookId, packageId);
|
||||
// update job status running
|
||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
.set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue())
|
||||
.set(JobEntity::getStartTimestamp, System.currentTimeMillis())
|
||||
.eq(JobEntity::getId, job.getId())
|
||||
);
|
||||
|
||||
JSONObject paramJSONObject = environment.getParamJSONObject();
|
||||
String url = paramJSONObject.getStr("url");
|
||||
String token = paramJSONObject.getStr("token");
|
||||
// add session
|
||||
EnvironmentSessionEntity session = new EnvironmentSessionEntity();
|
||||
session.setEnvId(envId);
|
||||
session.setJobId(job.getId());
|
||||
session.setStatus(1);
|
||||
session.setUserId("system");
|
||||
session.setWorkspaceId(job.getWorkspaceId());
|
||||
session.setStartTimestamp(System.currentTimeMillis());
|
||||
environmentSessionService.save(session);
|
||||
|
||||
File zipFile = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip"));
|
||||
HttpResponse response = requestEnvPlaybook(job, environment);
|
||||
log.info("[playbookExecutor] [job id: {}] [env: {}] [status: {}]", job.getId(), environment.getId(), response.getStatus());
|
||||
if (!response.isOk()) {
|
||||
|
||||
HttpRequest request = T.HttpUtil.createPost(String.format("%s/api/v1/env/playbook", url));
|
||||
T.ZipUtil.zip(zipFile, true, packageFile, playbookFile);
|
||||
request.form("file", zipFile);
|
||||
request.form("id", job.getId());
|
||||
request.form("packageName", packageName);
|
||||
request.header("Authorization", token);
|
||||
|
||||
HttpResponse response = request.execute();
|
||||
log.info("[playbookExecutor] [env: {}] [status: {}]", environment.getId(), response.getStatus());
|
||||
if (response.isOk()) {
|
||||
// update job status, starTime, updateTimestamp
|
||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
.set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue())
|
||||
.set(JobEntity::getStartTimestamp, System.currentTimeMillis())
|
||||
.eq(JobEntity::getId, job.getId())
|
||||
);
|
||||
|
||||
}else {
|
||||
String result = response.body();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[playbookExecutor] [env: {}] [result: {}]", environment.getId(), result);
|
||||
@@ -132,7 +137,6 @@ public class JobPlaybookExecutor extends QuartzJobBean {
|
||||
// update job status, starTime, updateTimestamp
|
||||
jobService.update(new LambdaUpdateWrapper<JobEntity>()
|
||||
.set(JobEntity::getStatus, RunnerConstant.JobStatus.FAILED.getValue())
|
||||
.set(JobEntity::getStartTimestamp, System.currentTimeMillis())
|
||||
.set(JobEntity::getEndTimestamp, System.currentTimeMillis())
|
||||
.eq(JobEntity::getId, job.getId()));
|
||||
}
|
||||
@@ -140,4 +144,32 @@ public class JobPlaybookExecutor extends QuartzJobBean {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private HttpResponse requestEnvPlaybook(JobEntity job, EnvironmentEntity environment) {
|
||||
String playbookId = job.getPlaybookId();
|
||||
String packageId = job.getPackageId();
|
||||
|
||||
PackageEntity packageEntity = packageService.getById(packageId);
|
||||
File packageFile = T.FileUtil.file(packageEntity.getPath());
|
||||
String packageName = packageEntity.getIdentifier();
|
||||
|
||||
PlaybookEntity playbook = playbookService.getById(playbookId);
|
||||
File playbookFile = T.FileUtil.file(playbook.getPath());
|
||||
|
||||
log.info("[playbookExecutor] [jobId: {}] [envId: {}] [playbookId: {}] [packageId: {}]", job.getId(), environment.getId(), playbookId, packageId);
|
||||
JSONObject paramJSONObject = environment.getParamJSONObject();
|
||||
String url = paramJSONObject.getStr("url");
|
||||
String token = paramJSONObject.getStr("token");
|
||||
File zipFile = T.FileUtil.file(Constants.TEMP_PATH, T.StrUtil.concat(true, job.getId(), ".zip"));
|
||||
|
||||
HttpRequest request = T.HttpUtil.createPost(String.format("%s/api/v1/env/playbook", url));
|
||||
T.ZipUtil.zip(zipFile, true, packageFile, playbookFile);
|
||||
request.form("file", zipFile);
|
||||
request.form("id", job.getId());
|
||||
request.form("packageName", packageName);
|
||||
request.header("Authorization", token);
|
||||
|
||||
HttpResponse response = request.execute();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.geedge.asw.module.runner.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
@@ -12,7 +13,9 @@ import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.PackageEntity;
|
||||
import net.geedge.asw.module.app.service.IPackageService;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentEntity;
|
||||
import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentService;
|
||||
import net.geedge.asw.module.environment.service.IEnvironmentSessionService;
|
||||
import net.geedge.asw.module.runner.dao.JobDao;
|
||||
import net.geedge.asw.module.runner.entity.JobEntity;
|
||||
import net.geedge.asw.module.runner.entity.PcapEntity;
|
||||
@@ -59,6 +62,9 @@ public class JobServiceImpl extends ServiceImpl<JobDao, JobEntity> implements IJ
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Autowired
|
||||
private IEnvironmentSessionService environmentSessionService;
|
||||
|
||||
|
||||
/**
|
||||
* rootPath/result/{jobId}
|
||||
@@ -95,6 +101,9 @@ public class JobServiceImpl extends ServiceImpl<JobDao, JobEntity> implements IJ
|
||||
WorkspaceEntity workspace = workspaceService.getById(job.getWorkspaceId());
|
||||
job.setWorkspace(workspace);
|
||||
|
||||
EnvironmentSessionEntity session = environmentSessionService.getOne(new LambdaQueryWrapper<EnvironmentSessionEntity>().eq(EnvironmentSessionEntity::getJobId, id));
|
||||
job.setSession(session);
|
||||
|
||||
if (-1 == job.getStartTimestamp()) {
|
||||
job.setStartTimestamp(null);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ public class SysAuthServiceImpl implements ISysAuthService {
|
||||
|
||||
@Override
|
||||
public SysUserEntity login(String userName, String pwd) {
|
||||
if (T.StrUtil.equals(userName, "system")) {
|
||||
throw ASWException.builder().rcode(RCode.SYS_SYSTEM_USER_NOT_LOGIN).build();
|
||||
}
|
||||
SysUserEntity userEntity = userDao
|
||||
.selectOne(new QueryWrapper<SysUserEntity>().lambda().eq(SysUserEntity::getUserName, userName));
|
||||
if (T.ObjectUtil.isNull(userEntity)
|
||||
|
||||
@@ -22,6 +22,7 @@ CREATE TABLE `sys_user` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
-- 添加内置用户
|
||||
INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `language`, `last_login_ip`, `last_login_timestamp`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', 'administrator', 'en', '', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, 'admin', 'admin');
|
||||
INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `language`, `last_login_ip`, `last_login_timestamp`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('system', 'system', 'system', 'ac45337abb5daec242e59aa5c9687', 'administrator', 'en', '', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, 'system', 'system');
|
||||
|
||||
/**
|
||||
* 1、新增 sys_role 表
|
||||
|
||||
Reference in New Issue
Block a user