diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketConnection.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketConnection.java index 1674e8f7..1a0b6770 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketConnection.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketConnection.java @@ -1,230 +1,230 @@ -package cd.casic.module.machine.component; - -import cd.casic.framework.commons.exception.ServiceException; -import cd.casic.module.machine.dal.dataobject.MachineInfoDO; -import cd.casic.module.machine.enums.AuthenticationType; -import cd.casic.module.machine.enums.ConnectionStatus; -import cd.casic.module.machine.enums.SSHChanelType; -import cd.casic.module.machine.service.SecretKeyService; -import com.jcraft.jsch.Channel; -import com.jcraft.jsch.ChannelExec; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Properties; - -import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; -import static cd.casic.module.machine.contants.MachineErrorCodeConstants.SECRET_KEY_NULL; -import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; - -@Slf4j -@Data -@Component -public class WebSocketConnection { - private SecretKeyService secretKeyService; - - private MachineInfoDO machineInfo; - private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED; - private Session sshSession; - - public WebSocketConnection(SecretKeyService secretKeyService) { - this.secretKeyService = secretKeyService; - } - - private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒) - - public void initConnection(MachineInfoDO machineInfo) { - try { - this.machineInfo = machineInfo; - this.sshSession = doConnect(machineInfo); - log.info("已成功建立 SSH 连接至 {} ", machineInfo.getHostIp()); - this.connectionStatus = ConnectionStatus.CONNECTING; - } catch (ServiceException e) { - log.warn("SSH 连接失败: {}", e.getMessage()); - throw e; - } - } - - public void disconnect() { - if (sshSession != null && sshSession.isConnected()) { - try { - sshSession.disconnect(); - log.info("SSH连接关闭: {}", machineInfo.getHostIp()); - } catch (Exception e) { - log.error("关闭SSH连接失败: {}", e.getMessage()); - throw exception(CLOSE_CLOSE_SESSION_ERROR); - } - } - connectionStatus = ConnectionStatus.DISCONNECTED; - } - - /** - * 执行远程命令,支持超时和中断处理 - */ - public void executeCommand(WebSocketSession webSocketSession, String command) { - // 1. 检查连接状态 - if (sshSession == null || !sshSession.isConnected()) { - sendErrorMessage(webSocketSession, "SSH连接未建立或已断开"); - return; - } - try { - // 2. 创建SSH命令执行通道 - Channel channel; - try { - channel = sshSession.openChannel(SSHChanelType.EXEC.getMessage()); - } catch (JSchException e) { - throw exception(CREATE_CHANEL_ERROR); - } - ((ChannelExec) channel).setCommand(command); - // 3. 设置输入/输出流 - channel.setInputStream(null); - ((ChannelExec) channel).setErrStream(System.err); - // 4. 获取命令输出流 - InputStream inputStream = channel.getInputStream(); - InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); - BufferedReader reader = new BufferedReader(inputStreamReader); - // 5. 连接并执行命令 - channel.connect(); - // 6. 读取命令输出并实时发送给客户端 - String line; - while ((line = reader.readLine()) != null) { - // 实时发送输出到客户端 - webSocketSession.sendMessage(new TextMessage(line)); - } - // 7. 等待命令执行完成 - int exitStatus = channel.getExitStatus(); - // 8. 发送命令执行完毕的消息 - webSocketSession.sendMessage(new TextMessage( - "[系统] 命令执行完毕,退出状态: " + exitStatus - )); - // 9. 关闭通道 - channel.disconnect(); - } catch (JSchException | IOException e) { - throw exception(EXECUTE_COMMAND_FAIL); - } - } - - // 发送错误消息的辅助方法 - public void sendErrorMessage(WebSocketSession webSocketSession, String message) { - try { - if (webSocketSession.isOpen()) { - webSocketSession.sendMessage(new TextMessage("[错误] " + message)); - } - } catch (IOException e) { - log.error("发送错误消息失败", e); - throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); - } - } - - /** - * 实际执行连接逻辑 - */ - private Session doConnect(MachineInfoDO machineInfo) { - JSch jsch = new JSch(); - // 配置认证方式 - configureAuthentication(jsch, machineInfo); - Session session; - // 创建SSH会话 - try { - session = jsch.getSession( - machineInfo.getUsername(), - machineInfo.getHostIp(), - machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22 - ); - } catch (JSchException e) { - throw exception(CREATE_SESSION_ERROR); - } - // 配置连接参数 - configureSession(session, machineInfo); - // 建立连接 - try { - session.connect(CONNECTION_TIMEOUT); - } catch (JSchException e) { - throw exception(SESSION_CONNECT_ERROR); - } - return session; - } - - /** - * 配置认证方式(密码或密钥) - */ - private void configureAuthentication(JSch jsch, MachineInfoDO machineInfo) { - if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY.getCode()) { - // 密钥认证 - if (machineInfo.getSecretKeyId() == null) { - throw exception(SECRET_KEY_NULL); - } - String pubKeyContent = secretKeyService.getKeyContent(machineInfo.getSecretKeyId()); - // 验证秘钥格式 - if (!pubKeyContent.startsWith("-----BEGIN")) { - log.error("无效的密钥格式{}", pubKeyContent); - throw exception(INVALID_kEY_FORMAT); - } - try { - // 尝试加载秘钥私钥 - jsch.addIdentity( - machineInfo.getName(), - pubKeyContent.getBytes(StandardCharsets.UTF_8), - null, - null - ); - log.info("密钥加载成功 {}", machineInfo.getHostIp()); - } catch (JSchException e) { - log.error("密钥加载失败: {}", e.getMessage()); - throw exception(READ_SECRET_CONTENT_ERROR); - } - } else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD.getCode()) { - // 密码认证 - if (!StringUtils.hasText(machineInfo.getPassword())) { - throw exception(PASSWORD_NOT_EXISTS); - } - } else { - log.error("不支持该验证类型:{}", machineInfo.getAuthenticationType()); - throw exception(NOT_SUPPORT_AUTHENTICATION_TYPE); - } - } - - /** - * 配置SSH会话参数(安全增强) - */ - private void configureSession(Session session, MachineInfoDO machineInfo) { - Properties config = new Properties(); - // 根据认证类型配置不同的认证策略 - if (machineInfo.getAuthenticationType() == 1) { // 密码认证 - // 设置密码 - session.setPassword(machineInfo.getPassword()); - config.put("StrictHostKeyChecking", "no"); - // 仅使用密码认证(禁用其他认证方式) - config.put("PreferredAuthentications", "password"); - // 禁用公钥相关配置(避免干扰) - config.put("PubkeyAuthentication", "no"); - } else { // 密钥认证 - try { - String preKeyPath = secretKeyService.getSecretKey(machineInfo.getSecretKeyId()).getPath(); - JSch jsch = new JSch(); - jsch.addIdentity(preKeyPath); // 添加私钥 - // 保持默认认证顺序(公钥优先) - config.put("PreferredAuthentications", "publicKey,password,keyboard-interactive"); - } catch (JSchException e) { - log.error("SSH密钥配置失败", e); - throw exception(SSH_KEY_CONFIGURATION_FAIL); - } - } - config.put("ServerAliveInterval", "30"); // 每30秒发送一次心跳 - config.put("ServerAliveCountMax", "3"); // 允许3次心跳失败 - session.setConfig(config); - } - -} +//package cd.casic.module.machine.component; +// +//import cd.casic.framework.commons.exception.ServiceException; +//import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +//import cd.casic.module.machine.enums.AuthenticationType; +//import cd.casic.module.machine.enums.ConnectionStatus; +//import cd.casic.module.machine.enums.SSHChanelType; +//import cd.casic.module.machine.service.SecretKeyService; +//import com.jcraft.jsch.Channel; +//import com.jcraft.jsch.ChannelExec; +//import com.jcraft.jsch.JSch; +//import com.jcraft.jsch.JSchException; +//import com.jcraft.jsch.Session; +//import lombok.Data; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.stereotype.Component; +//import org.springframework.util.StringUtils; +//import org.springframework.web.socket.TextMessage; +//import org.springframework.web.socket.WebSocketSession; +// +//import java.io.BufferedReader; +//import java.io.IOException; +//import java.io.InputStream; +//import java.io.InputStreamReader; +//import java.nio.charset.StandardCharsets; +//import java.util.Properties; +// +//import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +//import static cd.casic.module.machine.contants.MachineErrorCodeConstants.SECRET_KEY_NULL; +//import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; +// +//@Slf4j +//@Data +//@Component +//public class WebSocketConnection { +// private SecretKeyService secretKeyService; +// +// private MachineInfoDO machineInfo; +// private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED; +// private Session sshSession; +// +// public WebSocketConnection(SecretKeyService secretKeyService) { +// this.secretKeyService = secretKeyService; +// } +// +// private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒) +// +// public void initConnection(MachineInfoDO machineInfo) { +// try { +// this.machineInfo = machineInfo; +// this.sshSession = doConnect(machineInfo); +// log.info("已成功建立 SSH 连接至 {} ", machineInfo.getHostIp()); +// this.connectionStatus = ConnectionStatus.CONNECTING; +// } catch (ServiceException e) { +// log.warn("SSH 连接失败: {}", e.getMessage()); +// throw e; +// } +// } +// +// public void disconnect() { +// if (sshSession != null && sshSession.isConnected()) { +// try { +// sshSession.disconnect(); +// log.info("SSH连接关闭: {}", machineInfo.getHostIp()); +// } catch (Exception e) { +// log.error("关闭SSH连接失败: {}", e.getMessage()); +// throw exception(CLOSE_CLOSE_SESSION_ERROR); +// } +// } +// connectionStatus = ConnectionStatus.DISCONNECTED; +// } +// +// /** +// * 执行远程命令,支持超时和中断处理 +// */ +// public void executeCommand(WebSocketSession webSocketSession, String command) { +// // 1. 检查连接状态 +// if (sshSession == null || !sshSession.isConnected()) { +// sendErrorMessage(webSocketSession, "SSH连接未建立或已断开"); +// return; +// } +// try { +// // 2. 创建SSH命令执行通道 +// Channel channel; +// try { +// channel = sshSession.openChannel(SSHChanelType.EXEC.getMessage()); +// } catch (JSchException e) { +// throw exception(CREATE_CHANEL_ERROR); +// } +// ((ChannelExec) channel).setCommand(command); +// // 3. 设置输入/输出流 +// channel.setInputStream(null); +// ((ChannelExec) channel).setErrStream(System.err); +// // 4. 获取命令输出流 +// InputStream inputStream = channel.getInputStream(); +// InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); +// BufferedReader reader = new BufferedReader(inputStreamReader); +// // 5. 连接并执行命令 +// channel.connect(); +// // 6. 读取命令输出并实时发送给客户端 +// String line; +// while ((line = reader.readLine()) != null) { +// // 实时发送输出到客户端 +// webSocketSession.sendMessage(new TextMessage(line)); +// } +// // 7. 等待命令执行完成 +// int exitStatus = channel.getExitStatus(); +// // 8. 发送命令执行完毕的消息 +// webSocketSession.sendMessage(new TextMessage( +// "[系统] 命令执行完毕,退出状态: " + exitStatus +// )); +// // 9. 关闭通道 +// channel.disconnect(); +// } catch (JSchException | IOException e) { +// throw exception(EXECUTE_COMMAND_FAIL); +// } +// } +// +// // 发送错误消息的辅助方法 +// public void sendErrorMessage(WebSocketSession webSocketSession, String message) { +// try { +// if (webSocketSession.isOpen()) { +// webSocketSession.sendMessage(new TextMessage("[错误] " + message)); +// } +// } catch (IOException e) { +// log.error("发送错误消息失败", e); +// throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); +// } +// } +// +// /** +// * 实际执行连接逻辑 +// */ +// private Session doConnect(MachineInfoDO machineInfo) { +// JSch jsch = new JSch(); +// // 配置认证方式 +// configureAuthentication(jsch, machineInfo); +// Session session; +// // 创建SSH会话 +// try { +// session = jsch.getSession( +// machineInfo.getUsername(), +// machineInfo.getHostIp(), +// machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22 +// ); +// } catch (JSchException e) { +// throw exception(CREATE_SESSION_ERROR); +// } +// // 配置连接参数 +// configureSession(session, machineInfo); +// // 建立连接 +// try { +// session.connect(CONNECTION_TIMEOUT); +// } catch (JSchException e) { +// throw exception(SESSION_CONNECT_ERROR); +// } +// return session; +// } +// +//// /** +//// * 配置认证方式(密码或密钥) +//// */ +//// private void configureAuthentication(JSch jsch, MachineInfoDO machineInfo) { +//// if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY.getCode()) { +//// // 密钥认证 +//// if (machineInfo.getSecretKeyId() == null) { +//// throw exception(SECRET_KEY_NULL); +//// } +//// String pubKeyContent = secretKeyService.getKeyContent(machineInfo.getSecretKeyId()); +//// // 验证秘钥格式 +//// if (!pubKeyContent.startsWith("-----BEGIN")) { +//// log.error("无效的密钥格式{}", pubKeyContent); +//// throw exception(INVALID_kEY_FORMAT); +//// } +//// try { +//// // 尝试加载秘钥私钥 +//// jsch.addIdentity( +//// machineInfo.getName(), +//// pubKeyContent.getBytes(StandardCharsets.UTF_8), +//// null, +//// null +//// ); +//// log.info("密钥加载成功 {}", machineInfo.getHostIp()); +//// } catch (JSchException e) { +//// log.error("密钥加载失败: {}", e.getMessage()); +//// throw exception(READ_SECRET_CONTENT_ERROR); +//// } +//// } else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD.getCode()) { +//// // 密码认证 +//// if (!StringUtils.hasText(machineInfo.getPassword())) { +//// throw exception(PASSWORD_NOT_EXISTS); +//// } +//// } else { +//// log.error("不支持该验证类型:{}", machineInfo.getAuthenticationType()); +//// throw exception(NOT_SUPPORT_AUTHENTICATION_TYPE); +//// } +//// } +// +// /** +// * 配置SSH会话参数(安全增强) +// */ +// private void configureSession(Session session, MachineInfoDO machineInfo) { +// Properties config = new Properties(); +// // 根据认证类型配置不同的认证策略 +// if (machineInfo.getAuthenticationType() == 1) { // 密码认证 +// // 设置密码 +// session.setPassword(machineInfo.getPassword()); +// config.put("StrictHostKeyChecking", "no"); +// // 仅使用密码认证(禁用其他认证方式) +// config.put("PreferredAuthentications", "password"); +// // 禁用公钥相关配置(避免干扰) +// config.put("PubkeyAuthentication", "no"); +// } else { // 密钥认证 +// try { +// String preKeyPath = secretKeyService.getSecretKey(machineInfo.getSecretKeyId()).getPath(); +// JSch jsch = new JSch(); +// jsch.addIdentity(preKeyPath); // 添加私钥 +// // 保持默认认证顺序(公钥优先) +// config.put("PreferredAuthentications", "publicKey,password,keyboard-interactive"); +// } catch (JSchException e) { +// log.error("SSH密钥配置失败", e); +// throw exception(SSH_KEY_CONFIGURATION_FAIL); +// } +// } +// config.put("ServerAliveInterval", "30"); // 每30秒发送一次心跳 +// config.put("ServerAliveCountMax", "3"); // 允许3次心跳失败 +// session.setConfig(config); +// } +// +//} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketSessionManager.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketSessionManager.java index e07eab42..88c7acad 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketSessionManager.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketSessionManager.java @@ -1,114 +1,114 @@ -package cd.casic.module.machine.component; - -import org.springframework.stereotype.Component; -import org.springframework.web.socket.WebSocketSession; - -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; - -@Component("machineWebSocketSessionManger") -//管理webSocketSession -public class WebSocketSessionManager { - - //webSocketSessionId - WebSocketSession 保存 WebSocketSession 对象与会话 ID 的映射 - private static final ConcurrentHashMap WebSocketSessionMap = new ConcurrentHashMap<>(); - - //webSocketSessionId - WebSocketConnection 与远程机器的会话管理 - private static final ConcurrentHashMap sessionConnectionMap = new ConcurrentHashMap<>(); - - //机器id - WebSocketConnection - private static final ConcurrentHashMap webSocketSessionConnectionMap = new ConcurrentHashMap<>(); - - public static void addWebSocketSession(String sessionId, WebSocketSession session) { - WebSocketSessionMap.put(sessionId, session); - } - - /** - * 获取 WebSocketSession - */ - public static WebSocketSession getWebSocketSession(String sessionId) { - return WebSocketSessionMap.get(sessionId); - } - - /** - * 移除 WebSocketSession - */ - public static void removeWebSocketSession(String sessionId) { - WebSocketSessionMap.remove(sessionId); - } - - /** - * 检查 sessionId 是否存在 - */ - public static boolean containsWebSocketSession(String sessionId) { - return WebSocketSessionMap.containsKey(sessionId); - } - - /** - * 获取所有 WebSocketSession - */ - public static Collection getAllWebSocketSessions() { - return WebSocketSessionMap.values(); - } - - public static void addWebSocketConnection(String sessionId, WebSocketConnection connection) { - sessionConnectionMap.put(sessionId, connection); - } - - /** - * 获取 WebSocketConnection - */ - public static WebSocketConnection getWebSocketConnection(String sessionId) { - return sessionConnectionMap.get(sessionId); - } - - /** - * 移除 WebSocketConnection - */ - public static void removeWebSocketConnection(String sessionId) { - sessionConnectionMap.remove(sessionId); - } - - /** - * 检查 sessionId 是否存在 - */ - public static boolean containsWebSocketConnection(String sessionId) { - return sessionConnectionMap.containsKey(sessionId); - } - - /** - * 获取所有 WebSocketConnection - */ - public static ConcurrentHashMap getAllWebSocketConnections() { - return webSocketSessionConnectionMap; - } - - /** - * 添加 WebSocketConnection - */ - public static void addWebSocketConnectionByMachineId(Long machineId, WebSocketConnection connection) { - webSocketSessionConnectionMap.put(machineId, connection); - } - - /** - * 获取 WebSocketConnection - */ - public static WebSocketConnection getWebSocketConnectionByMachineId(Long machineId) { - return webSocketSessionConnectionMap.get(machineId); - } - - /** - * 移除 WebSocketConnection - */ - public static void removeWebSocketConnectionByMachineId(Long machineId) { - webSocketSessionConnectionMap.remove(machineId); - } - - /** - * 检查 machineId 是否存在 - */ - public static boolean containsMachineId(Long machineId) { - return webSocketSessionConnectionMap.containsKey(machineId); - } - -} +//package cd.casic.module.machine.component; +// +//import org.springframework.stereotype.Component; +//import org.springframework.web.socket.WebSocketSession; +// +//import java.util.Collection; +//import java.util.concurrent.ConcurrentHashMap; +// +//@Component("machineWebSocketSessionManger") +////管理webSocketSession +//public class WebSocketSessionManager { +// +// //webSocketSessionId - WebSocketSession 保存 WebSocketSession 对象与会话 ID 的映射 +// private static final ConcurrentHashMap WebSocketSessionMap = new ConcurrentHashMap<>(); +// +// //webSocketSessionId - WebSocketConnection 与远程机器的会话管理 +// private static final ConcurrentHashMap sessionConnectionMap = new ConcurrentHashMap<>(); +// +// //机器id - WebSocketConnection +// private static final ConcurrentHashMap webSocketSessionConnectionMap = new ConcurrentHashMap<>(); +// +// public static void addWebSocketSession(String sessionId, WebSocketSession session) { +// WebSocketSessionMap.put(sessionId, session); +// } +// +// /** +// * 获取 WebSocketSession +// */ +// public static WebSocketSession getWebSocketSession(String sessionId) { +// return WebSocketSessionMap.get(sessionId); +// } +// +// /** +// * 移除 WebSocketSession +// */ +// public static void removeWebSocketSession(String sessionId) { +// WebSocketSessionMap.remove(sessionId); +// } +// +// /** +// * 检查 sessionId 是否存在 +// */ +// public static boolean containsWebSocketSession(String sessionId) { +// return WebSocketSessionMap.containsKey(sessionId); +// } +// +// /** +// * 获取所有 WebSocketSession +// */ +// public static Collection getAllWebSocketSessions() { +// return WebSocketSessionMap.values(); +// } +// +// public static void addWebSocketConnection(String sessionId, WebSocketConnection connection) { +// sessionConnectionMap.put(sessionId, connection); +// } +// +// /** +// * 获取 WebSocketConnection +// */ +// public static WebSocketConnection getWebSocketConnection(String sessionId) { +// return sessionConnectionMap.get(sessionId); +// } +// +// /** +// * 移除 WebSocketConnection +// */ +// public static void removeWebSocketConnection(String sessionId) { +// sessionConnectionMap.remove(sessionId); +// } +// +// /** +// * 检查 sessionId 是否存在 +// */ +// public static boolean containsWebSocketConnection(String sessionId) { +// return sessionConnectionMap.containsKey(sessionId); +// } +// +// /** +// * 获取所有 WebSocketConnection +// */ +// public static ConcurrentHashMap getAllWebSocketConnections() { +// return webSocketSessionConnectionMap; +// } +// +// /** +// * 添加 WebSocketConnection +// */ +// public static void addWebSocketConnectionByMachineId(Long machineId, WebSocketConnection connection) { +// webSocketSessionConnectionMap.put(machineId, connection); +// } +// +// /** +// * 获取 WebSocketConnection +// */ +// public static WebSocketConnection getWebSocketConnectionByMachineId(Long machineId) { +// return webSocketSessionConnectionMap.get(machineId); +// } +// +// /** +// * 移除 WebSocketConnection +// */ +// public static void removeWebSocketConnectionByMachineId(Long machineId) { +// webSocketSessionConnectionMap.remove(machineId); +// } +// +// /** +// * 检查 machineId 是否存在 +// */ +// public static boolean containsMachineId(Long machineId) { +// return webSocketSessionConnectionMap.containsKey(machineId); +// } +// +//} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/configuration/WebSocketConfig.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/configuration/WebSocketConfig.java index c44d5d9e..00b84285 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/configuration/WebSocketConfig.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/configuration/WebSocketConfig.java @@ -1,40 +1,40 @@ -package cd.casic.module.machine.configuration; - -import cd.casic.module.machine.Interceptor.WebSocketHandshakeInterceptor; -import cd.casic.module.machine.handler.MachineWebSocketHandler; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.config.annotation.EnableWebSocket; -import org.springframework.web.socket.config.annotation.WebSocketConfigurer; -import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; -import org.springframework.web.socket.server.standard.ServerEndpointExporter; -import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; - -@Configuration -@EnableWebSocket -//WebSocket端点配置 -public class WebSocketConfig implements WebSocketConfigurer { - @Resource - private MachineWebSocketHandler machineWebSocketHandler; - - @Resource - private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor; - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(machineWebSocketHandler, "/ssh/terminal") - .addInterceptors(webSocketHandshakeInterceptor) - .setAllowedOrigins("*"); // 允许跨域(生产环境需限制) - } - - @Bean - public ServletServerContainerFactoryBean createWebSocketContainer() { - return new ServletServerContainerFactoryBean(); - } - - @Bean - public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); - } -} +//package cd.casic.module.machine.configuration; +// +//import cd.casic.module.machine.Interceptor.WebSocketHandshakeInterceptor; +//import cd.casic.module.machine.handler.MachineWebSocketHandler; +//import jakarta.annotation.Resource; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.socket.config.annotation.EnableWebSocket; +//import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +//import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; +//import org.springframework.web.socket.server.standard.ServerEndpointExporter; +//import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; +// +//@Configuration +//@EnableWebSocket +////WebSocket端点配置 +//public class WebSocketConfig implements WebSocketConfigurer { +// @Resource +// private MachineWebSocketHandler machineWebSocketHandler; +// +// @Resource +// private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor; +// +// @Override +// public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { +// registry.addHandler(machineWebSocketHandler, "/ssh/terminal") +// .addInterceptors(webSocketHandshakeInterceptor) +// .setAllowedOrigins("*"); // 允许跨域(生产环境需限制) +// } +// +// @Bean +// public ServletServerContainerFactoryBean createWebSocketContainer() { +// return new ServletServerContainerFactoryBean(); +// } +// +// @Bean +// public ServerEndpointExporter serverEndpointExporter() { +// return new ServerEndpointExporter(); +// } +//} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java index 8e4fbe4f..d3f66d82 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java @@ -78,38 +78,38 @@ public class MachineInfoController { return success(true); } - @GetMapping("/test") - @Operation(summary = "测试机器连接") - public CommonResult testConnection(@RequestParam("id") Long id) { - return success(machineInfoService.testConnection(id)); - } +// @GetMapping("/test") +// @Operation(summary = "测试机器连接") +// public CommonResult testConnection(@RequestParam("id") Long id) { +// return success(machineInfoService.testConnection(id)); +// } +// +// @GetMapping("/status") +// @Operation(summary = "获取机器连接状态") +// public CommonResult getConnectionStatus(@RequestParam Long id) { +// return success(machineInfoService.getConnectionStatus(id)); +// } +// +// @GetMapping("/status/all") +// @Operation(summary = "获取所有机器连接状态") +// public CommonResult> getAllConnectionStatus() { +// return success(machineInfoService.getAllConnectionStatus()); +// } +// +// @GetMapping("/connect") +// @Operation(summary = "建立连接") +// public CommonResult> connect(@RequestParam Long id) { +// return success(machineInfoService.connect(id)); +// } - @GetMapping("/status") - @Operation(summary = "获取机器连接状态") - public CommonResult getConnectionStatus(@RequestParam Long id) { - return success(machineInfoService.getConnectionStatus(id)); - } - - @GetMapping("/status/all") - @Operation(summary = "获取所有机器连接状态") - public CommonResult> getAllConnectionStatus() { - return success(machineInfoService.getAllConnectionStatus()); - } - - @GetMapping("/connect") - @Operation(summary = "建立连接") - public CommonResult> connect(@RequestParam Long id) { - return success(machineInfoService.connect(id)); - } - - @GetMapping("/fileTreeNode") - @Operation(summary = "获得文件树") - public CommonResult> fileTreeNode( - @RequestParam Long machineId, - @RequestParam(required = false, defaultValue = "/") String path - ) { - return CommonResult.success(machineInfoService.fileTreeNode(machineId, path)); - } +// @GetMapping("/fileTreeNode") +// @Operation(summary = "获得文件树") +// public CommonResult> fileTreeNode( +// @RequestParam Long machineId, +// @RequestParam(required = false, defaultValue = "/") String path +// ) { +// return CommonResult.success(machineInfoService.fileTreeNode(machineId, path)); +// } // @GetMapping("/upload") // @Operation(summary = "上传文件到远程机器") // public CommonResult uploadFile( diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java index 0b25a446..47d2810c 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java @@ -39,9 +39,11 @@ public class MachineInfoDO extends BaseDO { @TableField(value = "description") private String description; + //1:Linux 2:Windows @TableField(value = "machine_info_type") private Integer machineInfoType; + // 1:启用 0:停用 @TableField(value = "status") private Integer status; @@ -62,6 +64,7 @@ public class MachineInfoDO extends BaseDO { @TableField(value = "machine_proxy_id") private Long machineProxyId; + //1:密码认证 2:密钥认证 @TableField(value = "authentication_type") private Integer authenticationType; diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java index 349fe8ca..710dbd19 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java @@ -34,14 +34,12 @@ public class MachineProxyDO extends BaseDO { @TableField(value = "ssh_port") private String sshPort; - //todo 字典?? @TableField(value = "proxy_type") private int proxyType; @TableField(value = "version") private String version; - //todo 字典?? @TableField(value = "status") private int status; diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/MachineWebSocketHandler.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/MachineWebSocketHandler.java index acd353ea..ba6a0f6f 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/MachineWebSocketHandler.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/MachineWebSocketHandler.java @@ -1,67 +1,67 @@ -package cd.casic.module.machine.handler; - -import cd.casic.module.machine.component.WebSocketConnection; -import cd.casic.module.machine.component.WebSocketSessionManager; -import cd.casic.module.machine.enums.ConnectionStatus; -import org.jetbrains.annotations.NotNull; -import org.springframework.stereotype.Component; -import org.springframework.web.socket.CloseStatus; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; -import org.springframework.web.socket.handler.TextWebSocketHandler; - -import java.io.IOException; - -import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; -import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; - -//WebSocket处理器 -@Component("machineWebSocketHandler") -public class MachineWebSocketHandler extends TextWebSocketHandler { - - @Override - public void afterConnectionEstablished(@NotNull WebSocketSession webSocketSession) { - Long machineId = (Long) webSocketSession.getAttributes().get("machineId"); - //保存webSocketSession信息 - WebSocketSessionManager.addWebSocketSession(webSocketSession.getId(), webSocketSession); - WebSocketSessionManager.addWebSocketConnection(webSocketSession.getId(), WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId)); - try { - webSocketSession.sendMessage(new TextMessage("欢迎连接到 WebSocket 服务器!")); - } catch (IOException e) { - throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); - } - } - - // 处理文本消息 - @Override - protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) { - String payload = message.getPayload(); - String sessionId = webSocketSession.getId(); - // 从管理器获取连接 - WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); - - if (webSocketConnection != null && ConnectionStatus.CONNECTING.equals(webSocketConnection.getConnectionStatus())) { - // 转发消息到远程机器 - webSocketConnection.executeCommand(webSocketSession, payload); - } else if (webSocketConnection != null) { - webSocketConnection.sendErrorMessage(webSocketSession, "连接已断开,无法发送消息"); - } else { - throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); - } - } - - @Override - public void afterConnectionClosed(WebSocketSession webSocketSession, @NotNull CloseStatus status) { - String sessionId = webSocketSession.getId(); - // 获取并关闭相关的 WebSocketConnection - WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); - if (webSocketConnection != null) { - webSocketConnection.disconnect(); - } - // 从管理器中移除会话和连接 - WebSocketSessionManager.removeWebSocketSession(sessionId); - WebSocketSessionManager.removeWebSocketConnection(sessionId); - Long machineInfoId = (Long) webSocketSession.getAttributes().get("machineId"); - WebSocketSessionManager.removeWebSocketConnectionByMachineId(machineInfoId); - } -} +//package cd.casic.module.machine.handler; +// +////import cd.casic.module.machine.component.WebSocketConnection; +////import cd.casic.module.machine.component.WebSocketSessionManager; +//import cd.casic.module.machine.enums.ConnectionStatus; +//import org.jetbrains.annotations.NotNull; +//import org.springframework.stereotype.Component; +//import org.springframework.web.socket.CloseStatus; +//import org.springframework.web.socket.TextMessage; +//import org.springframework.web.socket.WebSocketSession; +//import org.springframework.web.socket.handler.TextWebSocketHandler; +// +//import java.io.IOException; +// +//import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +//import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; +// +////WebSocket处理器 +//@Component("machineWebSocketHandler") +//public class MachineWebSocketHandler extends TextWebSocketHandler { +// +// @Override +// public void afterConnectionEstablished(@NotNull WebSocketSession webSocketSession) { +// Long machineId = (Long) webSocketSession.getAttributes().get("machineId"); +// //保存webSocketSession信息 +// WebSocketSessionManager.addWebSocketSession(webSocketSession.getId(), webSocketSession); +// WebSocketSessionManager.addWebSocketConnection(webSocketSession.getId(), WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId)); +// try { +// webSocketSession.sendMessage(new TextMessage("欢迎连接到 WebSocket 服务器!")); +// } catch (IOException e) { +// throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); +// } +// } +// +// // 处理文本消息 +// @Override +// protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) { +// String payload = message.getPayload(); +// String sessionId = webSocketSession.getId(); +// // 从管理器获取连接 +// WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); +// +// if (webSocketConnection != null && ConnectionStatus.CONNECTING.equals(webSocketConnection.getConnectionStatus())) { +// // 转发消息到远程机器 +// webSocketConnection.executeCommand(webSocketSession, payload); +// } else if (webSocketConnection != null) { +// webSocketConnection.sendErrorMessage(webSocketSession, "连接已断开,无法发送消息"); +// } else { +// throw exception(WEBSOCKET_SEND_MESSAGE_ERROR); +// } +// } +// +// @Override +// public void afterConnectionClosed(WebSocketSession webSocketSession, @NotNull CloseStatus status) { +// String sessionId = webSocketSession.getId(); +// // 获取并关闭相关的 WebSocketConnection +// WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnection(sessionId); +// if (webSocketConnection != null) { +// webSocketConnection.disconnect(); +// } +// // 从管理器中移除会话和连接 +// WebSocketSessionManager.removeWebSocketSession(sessionId); +// WebSocketSessionManager.removeWebSocketConnection(sessionId); +// Long machineInfoId = (Long) webSocketSession.getAttributes().get("machineId"); +// WebSocketSessionManager.removeWebSocketConnectionByMachineId(machineInfoId); +// } +//} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java index 32efbadf..ea5fb26a 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java @@ -40,35 +40,35 @@ public interface MachineInfoService { ListselectBindMachineBySecretKey(Long secretKeyId); - /** - * 测试机器连接 - * - * @param id 机器id - * @return 连接是否成功 - */ - boolean testConnection(Long id); - - /** - * 连接远程机器 - * - * @param id 机器id - * @return 连接后端文件树 - */ - Map connect(Long id); - - /** - * 获取机器连接状态 - * - * @return 连接状态 - */ - ConnectionStatus getConnectionStatus(Long id); - - /** - * 获取所有连接状态 - * - * @return 机器名称到连接状态的映射 - */ - Map getAllConnectionStatus(); +// /** +// * 测试机器连接 +// * +// * @param id 机器id +// * @return 连接是否成功 +// */ +// boolean testConnection(Long id); +// +// /** +// * 连接远程机器 +// * +// * @param id 机器id +// * @return 连接后端文件树 +// */ +// Map connect(Long id); +// +// /** +// * 获取机器连接状态 +// * +// * @return 连接状态 +// */ +// ConnectionStatus getConnectionStatus(Long id); +// +// /** +// * 获取所有连接状态 +// * +// * @return 机器名称到连接状态的映射 +// */ +// Map getAllConnectionStatus(); // /** // * 上传文件到远程机器 @@ -97,12 +97,12 @@ public interface MachineInfoService { */ MachineInfoDO validateMachineInfoExists(Long id); - /** - * 根据路径获得远程文件树 - * - * @param machineId 机器id - * @param path 文件夹路径 - * @return 远程文件树 - */ - Map fileTreeNode(Long machineId, String path); +// /** +// * 根据路径获得远程文件树 +// * +// * @param machineId 机器id +// * @param path 文件夹路径 +// * @return 远程文件树 +// */ +// Map fileTreeNode(Long machineId, String path); } diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java index c26c2f23..99799623 100644 --- a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java @@ -2,7 +2,7 @@ package cd.casic.module.machine.service.impl; import cd.casic.framework.commons.pojo.PageResult; import cd.casic.module.machine.component.FileTreeComponent; -import cd.casic.module.machine.component.WebSocketSessionManager; +//import cd.casic.module.machine.component.WebSocketSessionManager; import cd.casic.module.machine.controller.vo.SecretKeyVO; import cd.casic.module.machine.enums.AuthenticationType; import cd.casic.module.machine.enums.MachineInfoType; @@ -11,7 +11,7 @@ import cd.casic.module.machine.controller.vo.MachineInfoVO; import cd.casic.module.machine.dal.dataobject.MachineInfoDO; import cd.casic.module.machine.enums.ConnectionStatus; import cd.casic.module.machine.enums.MachineInfoStatus; -import cd.casic.module.machine.component.WebSocketConnection; +//import cd.casic.module.machine.component.WebSocketConnection; import cd.casic.module.machine.service.MachineInfoService; import cd.casic.module.machine.service.SecretKeyService; import com.google.common.annotations.VisibleForTesting; @@ -113,43 +113,43 @@ public class MachineInfoServiceImpl implements MachineInfoService { } - @Override - public boolean testConnection(Long id) { - //先查询机器是否存在,在判断机器可用性 - MachineInfoDO machineInfoDO = validateMachineInfoExists(id); - validateMachineUnEnable(machineInfoDO); - log.info("测试机器连接: {}", machineInfoDO.getHostIp()); - WebSocketConnection webSocketConnection = createWebSocketConnection(machineInfoDO); - webSocketConnection.initConnection(machineInfoDO); - return true; - } - - @Override - public Map connect(Long id) { - //todo使用代理机器的情况还未完成 - WebSocketConnection webSocketConnection = new WebSocketConnection(this.secretKeyService); - MachineInfoDO machineInfoDO = validateMachineInfoExists(id); - //初始化连接 - webSocketConnection.initConnection(machineInfoDO); - WebSocketSessionManager.addWebSocketConnectionByMachineId(id, webSocketConnection); - return fileTreeComponent.getRemoteFileTree(webSocketConnection.getSshSession(), "/"); - } - - @Override - public ConnectionStatus getConnectionStatus(Long id) { - validateMachineInfoExists(id); - WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnectionByMachineId(id); - return webSocketConnection == null ? ConnectionStatus.DISCONNECTED : webSocketConnection.getConnectionStatus(); - } - - @Override - public Map getAllConnectionStatus() { - return WebSocketSessionManager.getAllWebSocketConnections().entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> entry.getValue().getConnectionStatus() - )); - } +// @Override +// public boolean testConnection(Long id) { +// //先查询机器是否存在,在判断机器可用性 +// MachineInfoDO machineInfoDO = validateMachineInfoExists(id); +// validateMachineUnEnable(machineInfoDO); +// log.info("测试机器连接: {}", machineInfoDO.getHostIp()); +// WebSocketConnection webSocketConnection = createWebSocketConnection(machineInfoDO); +// webSocketConnection.initConnection(machineInfoDO); +// return true; +// } +// +// @Override +// public Map connect(Long id) { +// //todo使用代理机器的情况还未完成 +// WebSocketConnection webSocketConnection = new WebSocketConnection(this.secretKeyService); +// MachineInfoDO machineInfoDO = validateMachineInfoExists(id); +// //初始化连接 +// webSocketConnection.initConnection(machineInfoDO); +// WebSocketSessionManager.addWebSocketConnectionByMachineId(id, webSocketConnection); +// return fileTreeComponent.getRemoteFileTree(webSocketConnection.getSshSession(), "/"); +// } +// +// @Override +// public ConnectionStatus getConnectionStatus(Long id) { +// validateMachineInfoExists(id); +// WebSocketConnection webSocketConnection = WebSocketSessionManager.getWebSocketConnectionByMachineId(id); +// return webSocketConnection == null ? ConnectionStatus.DISCONNECTED : webSocketConnection.getConnectionStatus(); +// } +// +// @Override +// public Map getAllConnectionStatus() { +// return WebSocketSessionManager.getAllWebSocketConnections().entrySet().stream() +// .collect(Collectors.toMap( +// Map.Entry::getKey, +// entry -> entry.getValue().getConnectionStatus() +// )); +// } // @Override // public boolean uploadFile(String sessionId, String localFilePath, String remoteFilePath) { @@ -246,12 +246,12 @@ public class MachineInfoServiceImpl implements MachineInfoService { return machineInfoDO; } - @Override - public Map fileTreeNode(Long machineId, String path) { - validateMachineInfoExists(machineId); - Session sshSession = WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId).getSshSession(); - return fileTreeComponent.getRemoteFileTree(sshSession, path); - } +// @Override +// public Map fileTreeNode(Long machineId, String path) { +// validateMachineInfoExists(machineId); +// Session sshSession = WebSocketSessionManager.getWebSocketConnectionByMachineId(machineId).getSshSession(); +// return fileTreeComponent.getRemoteFileTree(sshSession, path); +// } @VisibleForTesting void validateMachineEnable(MachineInfoDO machineInfoDO) { @@ -268,12 +268,12 @@ public class MachineInfoServiceImpl implements MachineInfoService { } } - @VisibleForTesting - WebSocketConnection createWebSocketConnection(MachineInfoDO machineInfoDO) { - if (WebSocketSessionManager.containsMachineId(machineInfoDO.getId())) { - return WebSocketSessionManager.getWebSocketConnectionByMachineId((machineInfoDO.getId())); - } else { - return new WebSocketConnection(this.secretKeyService); - } - } +// @VisibleForTesting +// WebSocketConnection createWebSocketConnection(MachineInfoDO machineInfoDO) { +// if (WebSocketSessionManager.containsMachineId(machineInfoDO.getId())) { +// return WebSocketSessionManager.getWebSocketConnectionByMachineId((machineInfoDO.getId())); +// } else { +// return new WebSocketConnection(this.secretKeyService); +// } +// } }