summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhangshuai <[email protected]>2024-11-11 09:41:41 +0800
committerzhangshuai <[email protected]>2024-11-11 09:41:41 +0800
commitd357daa29070a28779a4ec39751abd9ecbd02053 (patch)
tree74d75e8db23fbf8b0e089ef47501a8a76394eed2
parentc7c971d5087f85001c095ab87652108666e6b532 (diff)
fix: ASW-146 修复 job 执行时未修改 environment 状态和未添加session记录
-rw-r--r--src/main/java/net/geedge/asw/common/util/Constants.java6
-rw-r--r--src/main/java/net/geedge/asw/common/util/RCode.java1
-rw-r--r--src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java20
-rw-r--r--src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java2
-rw-r--r--src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java27
-rw-r--r--src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java6
-rw-r--r--src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecResultChecker.java100
-rw-r--r--src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java106
-rw-r--r--src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java9
-rw-r--r--src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java3
-rw-r--r--src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql1
11 files changed, 165 insertions, 116 deletions
diff --git a/src/main/java/net/geedge/asw/common/util/Constants.java b/src/main/java/net/geedge/asw/common/util/Constants.java
index 620856a..2300658 100644
--- a/src/main/java/net/geedge/asw/common/util/Constants.java
+++ b/src/main/java/net/geedge/asw/common/util/Constants.java
@@ -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
*/
diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java
index f2aed72..7cc834e 100644
--- a/src/main/java/net/geedge/asw/common/util/RCode.java
+++ b/src/main/java/net/geedge/asw/common/util/RCode.java
@@ -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
diff --git a/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java b/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java
index 1212233..1b0ea07 100644
--- a/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java
+++ b/src/main/java/net/geedge/asw/module/environment/controller/EnvironmentController.java
@@ -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();
}
diff --git a/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java b/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java
index fb98195..69668da 100644
--- a/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java
+++ b/src/main/java/net/geedge/asw/module/environment/service/IEnvironmentService.java
@@ -22,4 +22,6 @@ public interface IEnvironmentService extends IService<EnvironmentEntity>{
EnvironmentEntity saveEnv(EnvironmentEntity entity);
EnvironmentEntity updateEnv(EnvironmentEntity entity);
+
+ void removeSession(String sessionId);
}
diff --git a/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java b/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java
index 0fd80ca..4ccc15f 100644
--- a/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java
+++ b/src/main/java/net/geedge/asw/module/environment/service/impl/EnvironmentServiceImpl.java
@@ -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);
+ }
+ }
+
} \ No newline at end of file
diff --git a/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java b/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java
index ee3999b..c7caeb5 100644
--- a/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java
+++ b/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java
@@ -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;
+
+
+
} \ No newline at end of file
diff --git a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecResultChecker.java b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecResultChecker.java
index 5c848dd..5b1dff3 100644
--- a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecResultChecker.java
+++ b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecResultChecker.java
@@ -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;
}
}
diff --git a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java
index 5860318..8bddd32 100644
--- a/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java
+++ b/src/main/java/net/geedge/asw/module/runner/job/JobPlaybookExecutor.java
@@ -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());
-
- 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);
+ 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;
+ }
- 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())
- );
+ // 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())
+ );
+
+ // 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);
+
+ HttpResponse response = requestEnvPlaybook(job, environment);
+ log.info("[playbookExecutor] [job id: {}] [env: {}] [status: {}]", job.getId(), environment.getId(), response.getStatus());
+ if (!response.isOk()) {
- }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;
+ }
}
diff --git a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java
index 194114a..ff06638 100644
--- a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java
+++ b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java
@@ -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);
}
diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
index 2f938c1..71eb975 100644
--- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
+++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
@@ -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)
diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
index f63cb25..d235b8d 100644
--- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
+++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
@@ -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 表