pppoe功能增加
This commit is contained in:
@@ -16,4 +16,5 @@ public class ApplicationProperties {
|
||||
private String tmpPath;
|
||||
private String tempPath;
|
||||
private String frpPath;
|
||||
private String poePath;
|
||||
}
|
||||
@@ -69,6 +69,8 @@ public enum MsgEnum {
|
||||
|
||||
修改frp配置文件应答("UPDATE_FRP_RSP"),
|
||||
|
||||
macvlan状态上报("MACVLAN_STATUS_RSP"),
|
||||
|
||||
多网IP探测上报("NETWORK_DETECT");
|
||||
|
||||
private String value;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.tongran.agent.client.core.eo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PppoeConfigSubEO {
|
||||
/** 序号 */
|
||||
private Long serialNumber;
|
||||
|
||||
/** VLANID */
|
||||
private Long vlanId;
|
||||
|
||||
/** IPv4地址 */
|
||||
private String ipv4Address;
|
||||
|
||||
/** IPv4掩码位数 */
|
||||
private Long ipv4MaskBits;
|
||||
|
||||
/** IPv4网关 */
|
||||
private String ipv4Gateway;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.tongran.agent.client.core.eo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PppoeEO {
|
||||
/** 是否启用PPPoE(0-否,1-是) */
|
||||
private Long pppoeEnabled;
|
||||
|
||||
/** PPPoE配置方式 */
|
||||
private String pppoeConfigMode;
|
||||
|
||||
/** PPPoE网卡名称 */
|
||||
private String pppoeInterface;
|
||||
/** pppoe子表集合 */
|
||||
private List<PppoeConfigSubEO> subList;
|
||||
}
|
||||
@@ -34,6 +34,9 @@ public class CpuVO implements Serializable {
|
||||
@Schema(description = "CPU数量")
|
||||
private int num;
|
||||
|
||||
@Schema(description = "CPU核数")
|
||||
private int cores;
|
||||
|
||||
@Schema(description = "CPU正常运行时间:秒")
|
||||
private long normal;
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.tongran.agent.client.core.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MacVlanVO {
|
||||
/** 虚拟网卡id */
|
||||
private String vlanId;
|
||||
/** 编号 */
|
||||
private String mid;
|
||||
/** 状态 */
|
||||
private String status;
|
||||
}
|
||||
@@ -104,6 +104,10 @@ public class AppInitializer implements CommandLineRunner {
|
||||
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||
AssertLog.info("检测PppoE配置");
|
||||
agentService.handleRebootRecovery();
|
||||
AssertLog.info("启动macvlan状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 120000);
|
||||
dynamicTaskService.scheduleTask("upMacvlanStatus", businessTasks::upMacvlanStatus, 15000, 120000);
|
||||
}else{
|
||||
//未注册,发送注册
|
||||
try {
|
||||
|
||||
@@ -63,6 +63,7 @@ public class BusinessTasks {
|
||||
private final AtomicInteger checkFirewallTask = new AtomicInteger(0);
|
||||
private final AtomicInteger checkFrpcTask = new AtomicInteger(0);
|
||||
private final AtomicInteger upFrpcMsgTask = new AtomicInteger(0);
|
||||
private final AtomicInteger upMacvlanStatusTask = new AtomicInteger(0);
|
||||
|
||||
|
||||
|
||||
@@ -862,6 +863,10 @@ public class BusinessTasks {
|
||||
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||
AssertLog.info("检测PppoE配置");
|
||||
agentService.handleRebootRecovery();
|
||||
AssertLog.info("启动macvlan状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 120000);
|
||||
dynamicTaskService.scheduleTask("upMacvlanStatus", businessTasks::upMacvlanStatus, 15000, 120000);
|
||||
}else{
|
||||
//未注册,发送注册
|
||||
try {
|
||||
@@ -970,6 +975,40 @@ public class BusinessTasks {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务33:macvlan状态上报
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
public void upMacvlanStatus() {
|
||||
int count = upMacvlanStatusTask.incrementAndGet();
|
||||
AssertLog.info("macvlan状态上报定时任务执行 - 时间: {},task #{}", LocalDateTime.now(), count);
|
||||
// 判定客户端与服务端是否连接
|
||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||
if(StringUtils.isBlank(GlobalConfig.DEVICE_SN)){
|
||||
GlobalConfig.DEVICE_SN = AgentUtil.getDeviceSN();
|
||||
}
|
||||
long timestamps = System.currentTimeMillis();
|
||||
timestamps = Math.round(timestamps / 1000.0);
|
||||
List<MacVlanVO> macVlanVOList = null;
|
||||
try {
|
||||
macVlanVOList = agentService.upMacvlanStatus();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(macVlanVOList != null && !macVlanVOList.isEmpty()){
|
||||
JSONObject objects = new JSONObject();
|
||||
objects.put("clientId", GlobalConfig.CLIENT_ID);
|
||||
objects.put("macVlans", macVlanVOList);
|
||||
objects.put("timestamp", timestamps);
|
||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.macvlan状态上报.getValue()).data(objects.toString()).build();
|
||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||
AssertLog.info("发送macvlan状态上报信息包={}",JSON.toJSONString(message));
|
||||
}else {
|
||||
AssertLog.info("未检测到虚拟网卡,不进行macvlan状态上报");
|
||||
}
|
||||
}
|
||||
AssertLog.info("发送macvlan状态上报定时任务执行 - task #{} completed", count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.tongran.agent.client.service;
|
||||
|
||||
import com.tongran.agent.client.core.eo.ScriptPolicyEO;
|
||||
import com.tongran.agent.client.core.vo.MacVlanVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AgentService {
|
||||
void cancelCollect();
|
||||
@@ -42,4 +45,6 @@ public interface AgentService {
|
||||
void checkFrpc();
|
||||
|
||||
void upFrpcMsg();
|
||||
void handleRebootRecovery();
|
||||
List<MacVlanVO> upMacvlanStatus();
|
||||
}
|
||||
|
||||
@@ -7,11 +7,9 @@ import com.alibaba.fastjson2.TypeReference;
|
||||
import com.tongran.agent.client.core.config.ApplicationProperties;
|
||||
import com.tongran.agent.client.core.config.GlobalConfig;
|
||||
import com.tongran.agent.client.core.enums.MsgEnum;
|
||||
import com.tongran.agent.client.core.eo.AgentVersionUpdateEO;
|
||||
import com.tongran.agent.client.core.eo.CollectEO;
|
||||
import com.tongran.agent.client.core.eo.FrpMsgEO;
|
||||
import com.tongran.agent.client.core.eo.ScriptPolicyEO;
|
||||
import com.tongran.agent.client.core.eo.*;
|
||||
import com.tongran.agent.client.core.session.SessionManager;
|
||||
import com.tongran.agent.client.core.vo.MacVlanVO;
|
||||
import com.tongran.agent.client.netty.MultiTargetNettyClient;
|
||||
import com.tongran.agent.client.netty.config.AgentNettyConfig;
|
||||
import com.tongran.agent.client.netty.model.Message;
|
||||
@@ -23,6 +21,7 @@ import com.tongran.agent.client.scheduler.task.SpecificTimeRequest;
|
||||
import com.tongran.agent.client.scheduler.task.SpecificTimeTaskService;
|
||||
import com.tongran.agent.client.service.AgentService;
|
||||
import com.tongran.agent.client.utils.*;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@@ -319,6 +318,10 @@ public class AgentServiceImpl implements AgentService {
|
||||
dynamicTaskService.scheduleTask("checkFrpc", businessTasks::checkFrpcTask, 15000, 600000);
|
||||
AssertLog.info("启动frpc状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 300000);
|
||||
dynamicTaskService.scheduleTask("upFrpcMsg", businessTasks::upFrpcMsgTask, 15000, 300000);
|
||||
AssertLog.info("检测PppoE配置");
|
||||
handleRebootRecovery();
|
||||
AssertLog.info("启动macvlan状态上报定时任务 - 延迟: {}ms, 间隔: {}ms", 15000, 120000);
|
||||
dynamicTaskService.scheduleTask("upMacvlanStatus", businessTasks::upMacvlanStatus, 15000, 120000);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -898,8 +901,173 @@ public class AgentServiceImpl implements AgentService {
|
||||
restartFrpc(properties.getFrpPath());
|
||||
}
|
||||
}
|
||||
if(jsonObject.containsKey("pppoeConfig")){
|
||||
String pppoeConfig = jsonObject.getString("pppoeConfig");
|
||||
PppoeEO pppoeEO = JSON.parseObject(pppoeConfig, PppoeEO.class);
|
||||
handlePppoeConfig(pppoeEO);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 处理PPPoE配置
|
||||
* @param pppoeEO PPPoE配置对象
|
||||
*/
|
||||
private void handlePppoeConfig(PppoeEO pppoeEO) {
|
||||
if (pppoeEO == null) {
|
||||
AssertLog.error("PPPoE配置对象为空");
|
||||
return;
|
||||
}
|
||||
|
||||
Long enable = pppoeEO.getPppoeEnabled();
|
||||
if (enable == null) {
|
||||
AssertLog.error("PPPoE启用状态为空");
|
||||
return;
|
||||
}
|
||||
|
||||
String csvFilePath = properties.getPoePath() + "/macvlan_vlan.csv";
|
||||
|
||||
if (enable == 1L) {
|
||||
// 启用PPPoE时生成CSV文件
|
||||
try {
|
||||
generateCsvFile(pppoeEO, csvFilePath);
|
||||
updateAndExecuteScript(pppoeEO.getPppoeInterface(), csvFilePath);
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("生成CSV文件或执行脚本失败: {}", e.getMessage());
|
||||
}
|
||||
} else if (enable == 0L) {
|
||||
// 禁用PPPoE时删除CSV文件
|
||||
try {
|
||||
deleteCsvFile(csvFilePath);
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("删除CSV文件失败: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
AssertLog.error("无效的PPPoE启用状态: {}", enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成CSV文件
|
||||
* @param pppoeEO PPPoE配置对象
|
||||
* @param csvFilePath CSV文件路径
|
||||
*/
|
||||
private void generateCsvFile(PppoeEO pppoeEO, String csvFilePath) {
|
||||
if (pppoeEO.getSubList() == null || pppoeEO.getSubList().isEmpty()) {
|
||||
AssertLog.error("PPPoE子配置列表为空");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> csvLines = new ArrayList<>();
|
||||
for (PppoeConfigSubEO subConfig : pppoeEO.getSubList()) {
|
||||
String line = String.format("%d,%d,%s,%d,%s",
|
||||
subConfig.getVlanId(),
|
||||
subConfig.getSerialNumber(),
|
||||
subConfig.getIpv4Address(),
|
||||
subConfig.getIpv4MaskBits(),
|
||||
subConfig.getIpv4Gateway());
|
||||
csvLines.add(line);
|
||||
}
|
||||
|
||||
try {
|
||||
// 写入CSV文件
|
||||
FileUtils.writeLines(new File(csvFilePath), "UTF-8", csvLines);
|
||||
AssertLog.info("CSV文件生成成功: {}", csvFilePath);
|
||||
} catch (IOException e) {
|
||||
AssertLog.error("写入CSV文件失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除CSV文件
|
||||
* @param csvFilePath CSV文件路径
|
||||
*/
|
||||
private void deleteCsvFile(String csvFilePath) {
|
||||
File csvFile = new File(csvFilePath);
|
||||
if (csvFile.exists()) {
|
||||
try {
|
||||
FileUtils.forceDelete(csvFile);
|
||||
AssertLog.info("CSV文件删除成功: {}", csvFilePath);
|
||||
} catch (IOException e) {
|
||||
AssertLog.error("删除CSV文件失败: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
AssertLog.info("CSV文件不存在: {}", csvFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新脚本参数并执行
|
||||
* @param interfaceName 网卡名称
|
||||
* @param csvFilePath CSV文件路径
|
||||
*/
|
||||
private void updateAndExecuteScript(String interfaceName, String csvFilePath) {
|
||||
String scriptPath = properties.getPoePath() + "/multi_wan_conntrack.sh";
|
||||
File scriptFile = new File(scriptPath);
|
||||
|
||||
if (!scriptFile.exists()) {
|
||||
AssertLog.error("脚本文件不存在: {}", scriptPath);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String scriptContent = FileUtils.readFileToString(scriptFile, "UTF-8");
|
||||
|
||||
// 按行处理,替换参数
|
||||
String[] lines = scriptContent.split("\n");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
|
||||
// 替换PARENT_IF开头的行
|
||||
if (line.trim().startsWith("PARENT_IF=")) {
|
||||
lines[i] = String.format("PARENT_IF=\"%s\"", interfaceName);
|
||||
}
|
||||
|
||||
// 替换CSV开头的行
|
||||
if (line.trim().startsWith("CSV=")) {
|
||||
lines[i] = String.format("CSV=\"%s\"", csvFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// 重新组合内容
|
||||
scriptContent = String.join("\n", lines);
|
||||
FileUtils.writeStringToFile(scriptFile, scriptContent, "UTF-8");
|
||||
|
||||
// 给脚本添加执行权限
|
||||
if (!scriptFile.canExecute()) {
|
||||
scriptFile.setExecutable(true);
|
||||
}
|
||||
|
||||
// 修改这里:使用bash执行脚本,而不是source命令
|
||||
ProcessBuilder pb = new ProcessBuilder("/bin/bash", scriptPath);
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
// 设置工作目录
|
||||
pb.directory(new File(properties.getPoePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
|
||||
// 读取脚本输出
|
||||
StringBuilder output = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
AssertLog.info("脚本输出: {}", line);
|
||||
}
|
||||
}
|
||||
|
||||
int exitCode = process.waitFor();
|
||||
|
||||
if (exitCode == 0) {
|
||||
AssertLog.info("脚本执行成功: {}", scriptPath);
|
||||
} else {
|
||||
AssertLog.error("脚本执行失败,退出码: {},输出: {}", exitCode, output.toString());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("脚本执行失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
/** 启动frpc服务 */
|
||||
private void restartFrpc(String frpPath) {
|
||||
long timestamp = System.currentTimeMillis() / 1000;
|
||||
@@ -2099,4 +2267,132 @@ public class AgentServiceImpl implements AgentService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 重启恢复处理
|
||||
*/
|
||||
@Override
|
||||
public void handleRebootRecovery() {
|
||||
String csvFilePath = properties.getPoePath() + "/macvlan_vlan.csv";
|
||||
File csvFile = new File(csvFilePath);
|
||||
|
||||
// 检查CSV文件是否存在
|
||||
if (!csvFile.exists()) {
|
||||
AssertLog.info("CSV文件不存在,不执行脚本");
|
||||
return;
|
||||
}
|
||||
|
||||
AssertLog.info("CSV文件存在: {}", csvFilePath);
|
||||
|
||||
// 从CSV读取macvlan网卡名称
|
||||
String macvlanInterface = getFirstMacvlanFromCsv(csvFilePath);
|
||||
if (macvlanInterface == null) {
|
||||
AssertLog.error("无法从CSV文件中解析出macvlan网卡名称");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查网卡是否存在
|
||||
boolean interfaceExists = checkInterfaceExists(macvlanInterface);
|
||||
|
||||
if (!interfaceExists) {
|
||||
// CSV存在 && 网卡不存在 → 执行脚本
|
||||
AssertLog.info("macvlan网卡不存在: {},执行脚本", macvlanInterface);
|
||||
updateAndExecuteScript("eth0", csvFilePath);
|
||||
} else {
|
||||
// 其他情况都不执行
|
||||
AssertLog.info("macvlan网卡已存在: {},不执行脚本", macvlanInterface);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public List<MacVlanVO> upMacvlanStatus() {
|
||||
String csvFilePath = properties.getPoePath() + "/macvlan_vlan.csv";
|
||||
List<MacVlanVO> list = new ArrayList<>();
|
||||
try {
|
||||
List<String> lines = FileUtils.readLines(new File(csvFilePath), "UTF-8");
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty() || line.startsWith("#")) {
|
||||
continue; // 跳过空行和注释
|
||||
}
|
||||
String[] parts = line.split(",");
|
||||
if (parts.length >= 2) { // 至少需要vlan和mid
|
||||
String vlan = parts[0].trim();
|
||||
String mid = parts[1].trim();
|
||||
String interfaceName = String.format("xdbvl.%s.%s", vlan, mid);
|
||||
boolean interExites = checkInterfaceExists(interfaceName);
|
||||
if(interExites){
|
||||
// 检测与外网的连通性
|
||||
boolean status = getmacVlanStatus(interfaceName);
|
||||
MacVlanVO macVlanVO = new MacVlanVO();
|
||||
macVlanVO.setVlanId(vlan);
|
||||
macVlanVO.setMid(mid);
|
||||
macVlanVO.setStatus(status?"1":"0");
|
||||
list.add(macVlanVO);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("读取CSV文件失败: {}", e.getMessage());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从CSV读取第一个macvlan网卡名称
|
||||
*/
|
||||
private String getFirstMacvlanFromCsv(String csvFilePath) {
|
||||
try {
|
||||
List<String> lines = FileUtils.readLines(new File(csvFilePath), "UTF-8");
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty() || line.startsWith("#")) {
|
||||
continue; // 跳过空行和注释
|
||||
}
|
||||
String[] parts = line.split(",");
|
||||
if (parts.length >= 2) { // 至少需要vlan和mid
|
||||
String vlan = parts[0].trim();
|
||||
String mid = parts[1].trim();
|
||||
return String.format("xdbvl.%s.%s", vlan, mid);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("读取CSV文件失败: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private boolean getmacVlanStatus(String interfaceName) {
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder(
|
||||
"ping", "-I", interfaceName, "-c", "2", "-W", "2", "-4", "www.baidu.com"
|
||||
);
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
Process process = pb.start();
|
||||
boolean finished = process.waitFor(5, TimeUnit.SECONDS);
|
||||
|
||||
if (!finished) {
|
||||
process.destroy();
|
||||
AssertLog.warn("接口 {} ping超时", interfaceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return process.exitValue() == 0;
|
||||
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("接口 {} ping失败: {}", interfaceName, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查网卡是否存在
|
||||
*/
|
||||
private boolean checkInterfaceExists(String interfaceName) {
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder("ip", "link", "show", interfaceName);
|
||||
Process process = pb.start();
|
||||
return process.waitFor() == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class CPUServiceImpl implements CPUService {
|
||||
System.out.println("=========================================================");
|
||||
// 1. CPU基本信息
|
||||
cpuVO.setNum(processor.getPhysicalProcessorCount()); // CUP数量
|
||||
cpuVO.setCores(processor.getLogicalProcessorCount()); // CUP核数
|
||||
System.out.println("=== CPU基本信息 ===");
|
||||
System.out.println("CPU型号: " + processor.getProcessorIdentifier().getName());
|
||||
System.out.println("物理核心数: " + processor.getPhysicalProcessorCount());
|
||||
|
||||
Reference in New Issue
Block a user