Compare commits

...

2 Commits

Author SHA1 Message Date
唐潇凯
56150c156b Merge remote-tracking branch 'origin/jenkins-engin' into jenkins-engin 2025-06-05 11:01:56 +08:00
唐潇凯
891a332c59 机器连接修改 2025-06-05 11:00:54 +08:00
6 changed files with 54 additions and 40 deletions

View File

@ -69,8 +69,8 @@ public class MachineInfoController {
@PostMapping("/test")
@Operation(summary = "测试机器连接")
public CommonResult<Boolean> testConnection(@RequestBody MachineInfo machineInfo) {
return success(machineInfoService.testConnection(machineInfo));
public CommonResult<Boolean> testConnection(@RequestParam Long id) {
return success(machineInfoService.testConnection(id));
}
@GetMapping("/status/{machineName}")

View File

@ -30,7 +30,7 @@ public class MachineInfoDto extends PageDto {
private String status;
private String sshPort;
private Integer sshPort;
private String password;

View File

@ -46,7 +46,7 @@ public class MachineInfo extends BaseEntity {
private String username;
//SSH端口号
@TableField(value = "SSH_port")
@TableField(value = "ssh_port")
private Integer sshPort;
@TableField(value = "password")

View File

@ -1,18 +1,15 @@
package cd.casic.module.machine.handler;
import cd.casic.module.machine.utils.AliYunOssClient;
import cd.casic.module.machine.entity.MachineInfo;
import cd.casic.module.machine.entity.SecretKey;
import cd.casic.module.machine.enums.AuthenticationType;
import cd.casic.module.machine.enums.ConnectionStatus;
import cd.casic.module.machine.service.SecretKeyService;
import com.jcraft.jsch.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
@ -23,6 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* 优化后的SSH连接会话类
*/
@Slf4j
@Component
public class ConnectionSession implements AutoCloseable {
@Resource
SecretKeyService secretKeyService;
@ -30,21 +28,29 @@ public class ConnectionSession implements AutoCloseable {
@Resource
AliYunOssClient aliYunOssClient;
private final MachineInfo machineInfo;
private MachineInfo machineInfo;
private Session sshSession;
private ConnectionStatus status = ConnectionStatus.DISCONNECTED;
private final AtomicBoolean isExecuting = new AtomicBoolean(false);
// 连接配置常量
// todo连接配置常量
private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒)
private static final int COMMAND_TIMEOUT = 30000; // 命令执行超时时间(毫秒)
private static final int RETRY_COUNT = 3; // 重试次数
private static final int RETRY_DELAY = 1000; // 重试间隔(毫秒)
public ConnectionSession(MachineInfo machineInfo) {
this.machineInfo = Objects.requireNonNull(machineInfo, "MachineInfo cannot be null");
public ConnectionSession() {
}
// 使用setter注入MachineInfo
public void setMachineInfo(MachineInfo machineInfo) {
this.machineInfo = Objects.requireNonNull(machineInfo, "MachineInfo cannot be null");
log.debug("MachineInfo 已注入: {}", machineInfo.getHostIp());
}
/**
* 建立SSH连接支持重试机制
*/
@ -121,25 +127,32 @@ public class ConnectionSession implements AutoCloseable {
* 配置认证方式密码或密钥
*/
private void configureAuthentication(JSch jsch) throws JSchException {
if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY) {
if (machineInfo.getAuthenticationTypeCode() == 2) {
// 密钥认证
if (machineInfo.getSecretKeyId() == null) {
throw new JSchException("Secret key ID is required for key-based authentication");
}
String privateKeyContent = getPrivateKeyContent(machineInfo.getSecretKeyId());
if (StringUtils.isEmpty(privateKeyContent)) {
throw new JSchException("Private key content is empty or null for ID: " + machineInfo.getSecretKeyId());
// 验证私钥格式
if (!privateKeyContent.startsWith("-----BEGIN")) {
throw new JSchException("Invalid private key format. Expected OpenSSH format.");
}
// 加载私钥支持密码短语可从配置中获取
jsch.addIdentity(
machineInfo.getName(),
privateKeyContent.getBytes(StandardCharsets.UTF_8),
null,
null // 密码短语可为null
);
} else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD) {
try {
// 尝试加载私钥
jsch.addIdentity(
machineInfo.getName(),
privateKeyContent.getBytes(StandardCharsets.UTF_8),
null,
null
);
log.info("Private key loaded successfully for {}", machineInfo.getHostIp());
} catch (JSchException e) {
log.error("Failed to load private key: {}", e.getMessage());
throw e;
}
} else if (machineInfo.getAuthenticationTypeCode() == 1) {
// 密码认证
if (StringUtils.isEmpty(machineInfo.getPassword())) {
throw new JSchException("Password is required for password-based authentication");

View File

@ -28,10 +28,10 @@ public interface MachineInfoService extends IService<MachineInfo> {
/**
* 测试机器连接
*
* @param machineInfo 机器信息
* @param id 机器id
* @return 连接是否成功
*/
boolean testConnection(MachineInfo machineInfo);
boolean testConnection(Long id);
/**
* 获取机器连接状态

View File

@ -42,7 +42,8 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
@Resource
private MachineInfoMapper machineInfoMapper;
@Resource
private ConnectionSession connectionSession;
/**
* 会话ID生成器
*/
@ -184,14 +185,19 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
@Override
public boolean testConnection(MachineInfo machineInfo) {
if (machineInfo.getStatus().getCode() == UN_ENABLE) {
public boolean testConnection(Long id) {
//先查询机器是否存在在判断机器可用性
MachineInfo machineInfo = this.getById(id);
if (machineInfo==null){
throw new RuntimeException("机器不存在");
}
if (machineInfo.getStatusCode() == 0) {
throw new RuntimeException("机器不可用");
}
log.info("测试机器连接: {}", machineInfo.getHostIp());
try (ConnectionSession session = createSession(machineInfo)) {
session.connect();
connectionSession.setMachineInfo(machineInfo);
try{
connectionSession.connect();
return true;
} catch (Exception e) {
log.error("机器连接测试失败: {}", e.getMessage(), e);
@ -240,14 +246,15 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
}
try {
ConnectionSession session = createSession(machineInfo);
session.connect();
connectionSession.setMachineInfo(machineInfo);
connectionSession.connect();
// 生成会话ID
String sessionId = generateSessionId();
// 保存会话
sessions.put(sessionId, session);
sessions.put(sessionId, connectionSession);
machineSessionMapping.put(machineInfo.getName(), sessionId);
log.info("机器连接成功: {}, 会话ID: {}", machineInfo.getHostIp(), sessionId);
@ -346,12 +353,6 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
}
}
/**
* 创建连接会话
*/
private ConnectionSession createSession(MachineInfo machineInfo) {
return new ConnectionSession(machineInfo);
}
/**
* 生成会话ID