1、开发agent采集磁盘类型、磁盘已用空间方法。
2、开发磁盘测试IOPS方法。 3、开发磁盘分区卸载方法
This commit is contained in:
@@ -71,6 +71,8 @@ public enum MsgEnum {
|
|||||||
|
|
||||||
macvlan状态上报("MACVLAN_STATUS_RSP"),
|
macvlan状态上报("MACVLAN_STATUS_RSP"),
|
||||||
|
|
||||||
|
iops结果上报("IOPS_RESULT"),
|
||||||
|
|
||||||
多网IP探测上报("NETWORK_DETECT");
|
多网IP探测上报("NETWORK_DETECT");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ public class DiskVO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "时间戳")
|
@Schema(description = "时间戳")
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
@Schema(description = "磁盘类型")
|
||||||
|
private String type;
|
||||||
|
@Schema(description = "已用空间")
|
||||||
|
private long usedSpace;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,8 +907,157 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
PppoeEO pppoeEO = JSON.parseObject(pppoeConfig, PppoeEO.class);
|
PppoeEO pppoeEO = JSON.parseObject(pppoeConfig, PppoeEO.class);
|
||||||
handlePppoeConfig(pppoeEO);
|
handlePppoeConfig(pppoeEO);
|
||||||
}
|
}
|
||||||
|
if(jsonObject.containsKey("diskIopsTest")){
|
||||||
|
String diskName = jsonObject.getString("diskIopsTest");
|
||||||
|
handleDiskIops(diskName);
|
||||||
|
}
|
||||||
|
if(jsonObject.containsKey("umountDisk")){
|
||||||
|
String diskName = jsonObject.getString("umountDisk");
|
||||||
|
handleUmountDisk(diskName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleUmountDisk(String diskName) {
|
||||||
|
try {
|
||||||
|
// 查询所有挂载点
|
||||||
|
String[] grepCmd = {"sh", "-c", "mount | grep '" + diskName + "' | awk '{print $1}'"};
|
||||||
|
ProcessBuilder grepPb = new ProcessBuilder(grepCmd);
|
||||||
|
Process grepProcess = grepPb.start();
|
||||||
|
|
||||||
|
BufferedReader grepReader = new BufferedReader(new InputStreamReader(grepProcess.getInputStream()));
|
||||||
|
String partition;
|
||||||
|
List<String> partitions = new ArrayList<>();
|
||||||
|
|
||||||
|
// 收集所有分区
|
||||||
|
while ((partition = grepReader.readLine()) != null) {
|
||||||
|
partition = partition.trim();
|
||||||
|
if (!partition.isEmpty() && partition.startsWith("/dev/")) {
|
||||||
|
partitions.add(partition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grepReader.close();
|
||||||
|
grepProcess.waitFor();
|
||||||
|
|
||||||
|
// 如果没有分区,直接返回
|
||||||
|
if (partitions.isEmpty()) {
|
||||||
|
AssertLog.info("没有找到与{}相关的挂载分区", diskName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卸载所有分区
|
||||||
|
for (String part : partitions) {
|
||||||
|
try {
|
||||||
|
AssertLog.info("正在卸载:{}", part);
|
||||||
|
ProcessBuilder umountPb = new ProcessBuilder("umount", part);
|
||||||
|
Process umountProcess = umountPb.start();
|
||||||
|
int exitCode = umountProcess.waitFor();
|
||||||
|
|
||||||
|
if (exitCode == 0) {
|
||||||
|
AssertLog.info("成功卸载: {}", part);
|
||||||
|
} else {
|
||||||
|
// 尝试强制卸载
|
||||||
|
ProcessBuilder forcePb = new ProcessBuilder("umount", "-f", part);
|
||||||
|
Process forceProcess = forcePb.start();
|
||||||
|
int forceCode = forceProcess.waitFor();
|
||||||
|
|
||||||
|
if (forceCode == 0) {
|
||||||
|
AssertLog.info("强制卸载成功:{} ", part);
|
||||||
|
} else {
|
||||||
|
AssertLog.info("卸载失败: ", part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.info("卸载 {} 时出错: {}",diskName, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
AssertLog.info("卸载 {} 时出错: {}",diskName, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDiskIops(String diskName) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
AssertLog.info("开始测试磁盘{}的iops", diskName);
|
||||||
|
// 使用CompletableFuture并行执行
|
||||||
|
CompletableFuture<String> readFuture = CompletableFuture.supplyAsync(() -> {
|
||||||
|
return testIops(diskName, "read");
|
||||||
|
});
|
||||||
|
|
||||||
|
CompletableFuture<String> writeFuture = CompletableFuture.supplyAsync(() -> {
|
||||||
|
return testIops(diskName, "write");
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
timestamp = Math.round(timestamp / 1000.0);
|
||||||
|
// 等待两个测试都完成(最多70秒)
|
||||||
|
String readIops = readFuture.get(70, TimeUnit.SECONDS);
|
||||||
|
String writeIops = writeFuture.get(70, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
json.put("name", diskName);
|
||||||
|
json.put("readIops", readIops);
|
||||||
|
json.put("writeIops", writeIops);
|
||||||
|
json.put("timestamp",timestamp);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.iops结果上报.getValue())
|
||||||
|
.data(json.toString()).build();
|
||||||
|
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||||
|
AssertLog.info("发送iops结果上报应答={}",JSON.toJSONString(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.info("测试磁盘IOPS失败:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String testIops(String diskName, String rwType) {
|
||||||
|
try {
|
||||||
|
String cmd = String.format(
|
||||||
|
"fio --name=tt1 --filename=/dev/%s --size=1G --bs=4k --rw=%s --ioengine=libaio --runtime=60 --direct=1 --time_based --group_reporting",
|
||||||
|
diskName, rwType
|
||||||
|
);
|
||||||
|
|
||||||
|
Process process = Runtime.getRuntime().exec(new String[]{"bash", "-c", cmd});
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
output.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitFor();
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
return parseIops(output.toString());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("测试磁盘IOPS失败:{}", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseIops(String output) {
|
||||||
|
// 示例:" read: IOPS=12.7k, BW=49.6MiB/s (52.1MB/s)(2979MiB/60001msec)"
|
||||||
|
String[] lines = output.split("\n");
|
||||||
|
for (String line : lines) {
|
||||||
|
if (line.trim().startsWith("read:") || line.trim().startsWith("write:")) {
|
||||||
|
// 查找 IOPS= 部分
|
||||||
|
String[] parts = line.split("IOPS=");
|
||||||
|
if (parts.length > 1) {
|
||||||
|
String iopsPart = parts[1].split(",")[0];
|
||||||
|
return iopsPart.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理PPPoE配置
|
* 处理PPPoE配置
|
||||||
* @param pppoeEO PPPoE配置对象
|
* @param pppoeEO PPPoE配置对象
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import oshi.SystemInfo;
|
|||||||
import oshi.hardware.HWDiskStore;
|
import oshi.hardware.HWDiskStore;
|
||||||
import oshi.software.os.OSFileStore;
|
import oshi.software.os.OSFileStore;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.BufferedReader;
|
||||||
import java.util.List;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Objects;
|
import java.util.*;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DiskServiceImpl implements DiskService {
|
public class DiskServiceImpl implements DiskService {
|
||||||
@@ -19,29 +19,47 @@ public class DiskServiceImpl implements DiskService {
|
|||||||
public List<DiskVO> diskList(long timestamp) {
|
public List<DiskVO> diskList(long timestamp) {
|
||||||
List<DiskVO> tempList = new ArrayList<>();
|
List<DiskVO> tempList = new ArrayList<>();
|
||||||
List<DiskVO> resultList = new ArrayList<>();
|
List<DiskVO> resultList = new ArrayList<>();
|
||||||
|
Map<String, String> typeMap = getDiskTypeMap();
|
||||||
|
Map<String, Long> usedSpaceMap = getDiskUsedSpaceMap();
|
||||||
SystemInfo si = new SystemInfo();
|
SystemInfo si = new SystemInfo();
|
||||||
System.out.println("=========================================================");
|
System.out.println("=========================================================");
|
||||||
|
|
||||||
// 获取磁盘IO信息
|
// 获取磁盘IO信息
|
||||||
System.out.println("\n=== 磁盘IO信息 ===");
|
System.out.println("\n=== 磁盘IO信息 ===");
|
||||||
for (HWDiskStore disk : si.getHardware().getDiskStores()) {
|
for (HWDiskStore disk : si.getHardware().getDiskStores()) {
|
||||||
DiskVO diskVO = DiskVO.builder().timestamp(timestamp).build();
|
DiskVO diskVO = DiskVO.builder().timestamp(timestamp).build();
|
||||||
diskVO.setName(disk.getName());//磁盘名称
|
|
||||||
diskVO.setSerial(disk.getSerial());//序列号
|
// 处理磁盘名称:去掉/dev/前缀
|
||||||
diskVO.setTotal(disk.getSize());//磁盘大小
|
String diskFullName = disk.getName();
|
||||||
diskVO.setWriteTimes(disk.getWrites());//磁盘写入次数
|
String diskName = diskFullName.replace("/dev/", "");
|
||||||
diskVO.setReadTimes(disk.getReads());//磁盘读取次数
|
diskVO.setName(diskName); // 保持原样存储
|
||||||
diskVO.setWriteBytes(disk.getReadBytes());//磁盘写入字节
|
diskVO.setSerial(disk.getSerial()); // 序列号
|
||||||
diskVO.setReadBytes(disk.getWriteBytes());//磁盘读取字节
|
diskVO.setTotal(disk.getSize()); // 磁盘大小
|
||||||
|
diskVO.setWriteTimes(disk.getWrites()); // 磁盘写入次数
|
||||||
|
diskVO.setReadTimes(disk.getReads()); // 磁盘读取次数
|
||||||
|
diskVO.setWriteBytes(disk.getReadBytes()); // 磁盘写入字节
|
||||||
|
diskVO.setReadBytes(disk.getWriteBytes()); // 磁盘读取字节
|
||||||
|
|
||||||
|
// 获取磁盘类型和已用空间(使用不带/dev/前缀的名称)
|
||||||
|
String type = typeMap.get(diskName);
|
||||||
|
Long usedSpace = usedSpaceMap.get(diskName);
|
||||||
|
|
||||||
|
diskVO.setType(type != null ? type : "UNKNOWN");
|
||||||
|
diskVO.setUsedSpace(usedSpace != null ? usedSpace : 0L);
|
||||||
|
|
||||||
tempList.add(diskVO);
|
tempList.add(diskVO);
|
||||||
|
|
||||||
System.out.println("磁盘名称: " + diskVO.getName());
|
System.out.println("磁盘名称: " + diskVO.getName());
|
||||||
System.out.println("序列号: " + diskVO.getSerial());
|
System.out.println("序列号: " + diskVO.getSerial());
|
||||||
|
System.out.println("磁盘类型: " + diskVO.getType());
|
||||||
|
System.out.println("已用空间: " + diskVO.getUsedSpace());
|
||||||
System.out.println("磁盘大小: " + diskVO.getTotal());
|
System.out.println("磁盘大小: " + diskVO.getTotal());
|
||||||
System.out.println("磁盘写入次数: " + diskVO.getWriteTimes());
|
System.out.println("磁盘写入次数: " + diskVO.getWriteTimes());
|
||||||
System.out.println("磁盘读取次数: " + diskVO.getReadTimes());
|
System.out.println("磁盘读取次数: " + diskVO.getReadTimes());
|
||||||
System.out.println("磁盘写入字节: " + diskVO.getWriteBytes());
|
System.out.println("磁盘写入字节: " + diskVO.getWriteBytes());
|
||||||
System.out.println("磁盘读取字节: " + diskVO.getReadBytes());
|
System.out.println("磁盘读取字节: " + diskVO.getReadBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
// 第一次采样
|
// 第一次采样
|
||||||
List<HWDiskStore> disks1 = si.getHardware().getDiskStores();
|
List<HWDiskStore> disks1 = si.getHardware().getDiskStores();
|
||||||
@@ -64,6 +82,8 @@ public class DiskServiceImpl implements DiskService {
|
|||||||
diskVO.setWriteSpeed(readDiff);//磁盘写入速率
|
diskVO.setWriteSpeed(readDiff);//磁盘写入速率
|
||||||
diskVO.setReadSpeed(writeDiff);//磁盘读取速率
|
diskVO.setReadSpeed(writeDiff);//磁盘读取速率
|
||||||
System.out.println("磁盘名称: " + diskVO.getName());
|
System.out.println("磁盘名称: " + diskVO.getName());
|
||||||
|
System.out.println("磁盘类型: " + diskVO.getType());
|
||||||
|
System.out.println("已用空间: " + diskVO.getUsedSpace());
|
||||||
System.out.println("磁盘写入速率: " + diskVO.getWriteSpeed());
|
System.out.println("磁盘写入速率: " + diskVO.getWriteSpeed());
|
||||||
System.out.println("磁盘读取速率: " + diskVO.getReadSpeed());
|
System.out.println("磁盘读取速率: " + diskVO.getReadSpeed());
|
||||||
}
|
}
|
||||||
@@ -75,6 +95,128 @@ public class DiskServiceImpl implements DiskService {
|
|||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取磁盘类型映射(设备名 -> 类型)
|
||||||
|
*/
|
||||||
|
public Map<String, String> getDiskTypeMap() {
|
||||||
|
Map<String, String> diskTypeMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("lsblk", "-d", "-o", "name,rota");
|
||||||
|
Process process = pb.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
reader.readLine(); // 跳过标题行
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String[] parts = line.trim().split("\\s+");
|
||||||
|
if (parts.length >= 2) {
|
||||||
|
String diskName = parts[0];
|
||||||
|
String rota = parts[1];
|
||||||
|
String type = "1".equals(rota) ? "HDD" : "SSD";
|
||||||
|
|
||||||
|
diskTypeMap.put(diskName, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return diskTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取磁盘已用空间映射(设备名 -> 已用字节数)
|
||||||
|
* 使用lsblk获取准确的磁盘-分区关系
|
||||||
|
*/
|
||||||
|
public Map<String, Long> getDiskUsedSpaceMap() {
|
||||||
|
Map<String, Long> diskUsedMap = new HashMap<>();
|
||||||
|
Map<String, String> partitionToDisk = getPartitionToDiskMap();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("df", "-B1", "--output=source,used");
|
||||||
|
Process process = pb.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
reader.readLine(); // 跳过标题行
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = line.trim();
|
||||||
|
if (line.isEmpty() || line.startsWith("Filesystem")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = line.split("\\s+");
|
||||||
|
if (parts.length >= 2 && parts[0].startsWith("/dev/")) {
|
||||||
|
String device = parts[0];
|
||||||
|
String usedStr = parts[1];
|
||||||
|
|
||||||
|
try {
|
||||||
|
long used = Long.parseLong(usedStr);
|
||||||
|
String deviceName = device.replace("/dev/", "");
|
||||||
|
|
||||||
|
// 通过lsblk获取的映射关系找到对应的物理磁盘
|
||||||
|
String diskName = partitionToDisk.get(deviceName);
|
||||||
|
if (diskName == null) {
|
||||||
|
// 如果没有找到映射,可能是磁盘本身(不是分区)
|
||||||
|
diskName = deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diskName != null) {
|
||||||
|
diskUsedMap.merge(diskName, used, Long::sum);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return diskUsedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用lsblk获取磁盘-分区映射关系
|
||||||
|
* @return Map<分区设备名, 物理磁盘设备名>
|
||||||
|
*/
|
||||||
|
private Map<String, String> getPartitionToDiskMap() {
|
||||||
|
Map<String, String> partitionToDiskMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("lsblk", "-l", "-o", "name,type");
|
||||||
|
Process process = pb.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
reader.readLine(); // 跳过标题行
|
||||||
|
String currentDisk = null;
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = line.trim();
|
||||||
|
if (line.isEmpty()) continue;
|
||||||
|
|
||||||
|
String[] parts = line.split("\\s+");
|
||||||
|
if (parts.length >= 2) {
|
||||||
|
String device = parts[0];
|
||||||
|
String type = parts[1];
|
||||||
|
|
||||||
|
if ("disk".equals(type)) {
|
||||||
|
// 这是物理磁盘
|
||||||
|
currentDisk = device;
|
||||||
|
} else if ("part".equals(type) && currentDisk != null) {
|
||||||
|
// 这是分区,关联到当前磁盘
|
||||||
|
partitionToDiskMap.put(device, currentDisk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
process.waitFor();
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return partitionToDiskMap;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public List<PointVO> pointList(long timestamp) {
|
public List<PointVO> pointList(long timestamp) {
|
||||||
List<PointVO> list = new ArrayList<>();
|
List<PointVO> list = new ArrayList<>();
|
||||||
|
|||||||
Reference in New Issue
Block a user