fix: plp 输出展示错误
This commit is contained in:
parent
3c1cc26896
commit
a1c99352a8
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,7 +22,6 @@ mem.pprof
|
|||||||
# Go语言相关
|
# Go语言相关
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
/pkg/
|
|
||||||
/vendor/
|
/vendor/
|
||||||
|
|
||||||
# IDE和编辑器文件
|
# IDE和编辑器文件
|
||||||
|
@ -196,7 +196,7 @@ func (c *Client) MonitorTestStatus(testID string) error {
|
|||||||
return
|
return
|
||||||
case "integrity":
|
case "integrity":
|
||||||
if info, ok := update.Data.(map[string]interface{}); ok {
|
if info, ok := update.Data.(map[string]interface{}); ok {
|
||||||
c.logger.Infof("数据完整性: 可用块: %.0f, 损坏块: %.0f, 丢失块: %.0f, 数据丢失: %.2f MB",
|
c.logger.Infof("数据完整性: 可用块: %.0f, 损坏块: %.0f, 没写入块: %.0f, 数据丢失: %.2f MB",
|
||||||
info["available_blocks"], info["corrupted_blocks"], info["missing_blocks"], info["data_loss_mb"])
|
info["available_blocks"], info["corrupted_blocks"], info["missing_blocks"], info["data_loss_mb"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,11 +487,12 @@ func StartServer(cfg *config.Config, runner *TestRunner, logger *logrus.Logger)
|
|||||||
// 保存完整性信息
|
// 保存完整性信息
|
||||||
runner.SaveIntegrityInfo(testID, integrityInfo)
|
runner.SaveIntegrityInfo(testID, integrityInfo)
|
||||||
|
|
||||||
// 发送完整性信息
|
// 发送完整性信息 && BlocksMap 清理掉
|
||||||
|
integrityInfo.BlocksMap = nil
|
||||||
|
|
||||||
runner.sendIntegrityUpdate(testID, "数据完整性检查完成", integrityInfo)
|
runner.sendIntegrityUpdate(testID, "数据完整性检查完成", integrityInfo)
|
||||||
|
|
||||||
logger.Infof("恢复测试完成: 丢失数据: %.2f MB", integrityInfo.DataLossMB)
|
logger.Infof("恢复测试完成: 没填充的数据: %.2f MB", integrityInfo.DataLossMB)
|
||||||
} else {
|
} else {
|
||||||
logger.Error("不是断电测试实例,无法执行数据完整性检查")
|
logger.Error("不是断电测试实例,无法执行数据完整性检查")
|
||||||
runner.sendErrorUpdate(testID, "不是断电测试实例,无法执行数据完整性检查")
|
runner.sendErrorUpdate(testID, "不是断电测试实例,无法执行数据完整性检查")
|
||||||
|
@ -403,7 +403,7 @@ func (t *PowerLossTest) CheckIntegrity() *model.IntegrityInfo {
|
|||||||
t.integrityInfo.DataLossMB = utils.BytesToMB((t.integrityInfo.MissingBlocks + t.integrityInfo.CorruptedBlocks) * t.blockSize)
|
t.integrityInfo.DataLossMB = utils.BytesToMB((t.integrityInfo.MissingBlocks + t.integrityInfo.CorruptedBlocks) * t.blockSize)
|
||||||
t.integrityInfo.RecoverySuccess = t.integrityInfo.CorruptedBlocks == 0 && t.integrityInfo.MissingBlocks == 0
|
t.integrityInfo.RecoverySuccess = t.integrityInfo.CorruptedBlocks == 0 && t.integrityInfo.MissingBlocks == 0
|
||||||
|
|
||||||
t.setMessage(fmt.Sprintf("数据完整性检查完成: %d 个块正常, %d 个块丢失, %d 个块损坏",
|
t.setMessage(fmt.Sprintf("数据完整性检查完成: %d 个块正常, %d 个块没写入, %d 个块损坏",
|
||||||
t.integrityInfo.AvailableBlocks, t.integrityInfo.MissingBlocks, t.integrityInfo.CorruptedBlocks))
|
t.integrityInfo.AvailableBlocks, t.integrityInfo.MissingBlocks, t.integrityInfo.CorruptedBlocks))
|
||||||
|
|
||||||
return t.integrityInfo
|
return t.integrityInfo
|
||||||
|
269
pkg/opencastools/opencas.go
Normal file
269
pkg/opencastools/opencas.go
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
package opencastools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"plp-test/internal/utils"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CacheInstance 表示Open-CAS缓存实例
|
||||||
|
type CacheInstance struct {
|
||||||
|
ID string
|
||||||
|
CacheDevice string
|
||||||
|
CoreDevice string
|
||||||
|
CacheMode string
|
||||||
|
Status string
|
||||||
|
WritePolicy string
|
||||||
|
Mounted bool
|
||||||
|
MountPoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenCASManager 管理Open-CAS实例
|
||||||
|
type OpenCASManager struct {
|
||||||
|
logger *logrus.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOpenCASManager 创建OpenCAS管理器
|
||||||
|
func NewOpenCASManager(logger *logrus.Logger) *OpenCASManager {
|
||||||
|
return &OpenCASManager{
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCacheInstance 创建一个Open-CAS缓存实例
|
||||||
|
func (m *OpenCASManager) CreateCacheInstance(id string, cacheDevice, coreDevice, cacheMode string) error {
|
||||||
|
m.logger.Infof("创建缓存实例 %s: 缓存设备=%s, 核心设备=%s, 模式=%s", id, cacheDevice, coreDevice, cacheMode)
|
||||||
|
|
||||||
|
// 检查设备是否存在
|
||||||
|
if !utils.FileExists(cacheDevice) {
|
||||||
|
return fmt.Errorf("缓存设备不存在: %s", cacheDevice)
|
||||||
|
}
|
||||||
|
if !utils.FileExists(coreDevice) {
|
||||||
|
return fmt.Errorf("核心设备不存在: %s", coreDevice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查设备是否已被使用
|
||||||
|
output, err := utils.ExecuteCommand("casadm", "-L")
|
||||||
|
if err == nil && strings.Contains(output, cacheDevice) {
|
||||||
|
return fmt.Errorf("缓存设备已在使用中: %s", cacheDevice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动缓存
|
||||||
|
_, err = utils.ExecuteCommand("casadm", "-S", "-d", cacheDevice, "-i", id, "-c", cacheMode)
|
||||||
|
if err != nil {
|
||||||
|
msg, err := utils.ExecuteCommand("casadm", "-S", "-d", cacheDevice, "--load")
|
||||||
|
if err != nil && !strings.Contains(msg, "is already used as cache") {
|
||||||
|
return fmt.Errorf("启动缓存失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加核心设备
|
||||||
|
msg, err := utils.ExecuteCommand("casadm", "-A", "-i", id, "-d", coreDevice)
|
||||||
|
if err != nil && !strings.Contains(msg, "Device already added as a core") {
|
||||||
|
// 如果添加核心设备失败,尝试停止缓存
|
||||||
|
utils.ExecuteCommand("casadm", "-T", "-i", id)
|
||||||
|
return fmt.Errorf("添加核心设备失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.logger.Infof("缓存实例 %s 创建成功", id)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopCacheInstance 停止缓存实例
|
||||||
|
func (m *OpenCASManager) StopCacheInstance(id string) error {
|
||||||
|
m.logger.Infof("停止缓存实例 %s", id)
|
||||||
|
_, err := utils.ExecuteCommand("casadm", "-T", "-i", id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("停止缓存实例失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCacheStatus 获取缓存状态
|
||||||
|
func (m *OpenCASManager) GetCacheStatus(id string) (*CacheInstance, error) {
|
||||||
|
output, err := utils.ExecuteCommand("casadm", "-L")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("获取缓存状态失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析输出以查找指定ID的缓存实例
|
||||||
|
lines := strings.Split(output, "\n")
|
||||||
|
var cacheInfo, coreInfo string
|
||||||
|
for i, line := range lines {
|
||||||
|
if strings.Contains(line, "cache "+id) {
|
||||||
|
if i+1 < len(lines) {
|
||||||
|
cacheInfo = lines[i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.Contains(line, "└─") && strings.Contains(line, "core") {
|
||||||
|
coreInfo = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cacheInfo == "" {
|
||||||
|
return nil, fmt.Errorf("未找到ID为 %s 的缓存实例", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取缓存信息
|
||||||
|
instance := &CacheInstance{
|
||||||
|
ID: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取缓存设备
|
||||||
|
cacheDevicePattern := regexp.MustCompile(`/dev/\w+`)
|
||||||
|
cacheMatches := cacheDevicePattern.FindStringSubmatch(cacheInfo)
|
||||||
|
if len(cacheMatches) > 0 {
|
||||||
|
instance.CacheDevice = cacheMatches[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取核心设备
|
||||||
|
coreMatches := cacheDevicePattern.FindStringSubmatch(coreInfo)
|
||||||
|
if len(coreMatches) > 0 {
|
||||||
|
instance.CoreDevice = coreMatches[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取缓存模式
|
||||||
|
if strings.Contains(cacheInfo, "wb") {
|
||||||
|
instance.CacheMode = "Write-Back"
|
||||||
|
instance.WritePolicy = "Write-Back"
|
||||||
|
} else if strings.Contains(cacheInfo, "wt") {
|
||||||
|
instance.CacheMode = "Write-Through"
|
||||||
|
instance.WritePolicy = "Write-Through"
|
||||||
|
} else if strings.Contains(cacheInfo, "wo") {
|
||||||
|
instance.CacheMode = "Write-Only"
|
||||||
|
instance.WritePolicy = "Write-Only"
|
||||||
|
} else if strings.Contains(cacheInfo, "pt") {
|
||||||
|
instance.CacheMode = "Pass-Through"
|
||||||
|
instance.WritePolicy = "Pass-Through"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查状态
|
||||||
|
if strings.Contains(cacheInfo, "Running") {
|
||||||
|
instance.Status = "Running"
|
||||||
|
} else if strings.Contains(cacheInfo, "Stopping") {
|
||||||
|
instance.Status = "Stopping"
|
||||||
|
} else {
|
||||||
|
instance.Status = "Unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已挂载
|
||||||
|
cacheDevicePath := fmt.Sprintf("/dev/cas%s-1", id)
|
||||||
|
instance.Mounted = utils.IsMounted(cacheDevicePath)
|
||||||
|
|
||||||
|
// 如果已挂载,尝试获取挂载点
|
||||||
|
if instance.Mounted {
|
||||||
|
output, err := utils.ExecuteCommand("mount")
|
||||||
|
if err == nil {
|
||||||
|
lines = strings.Split(output, "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(line, cacheDevicePath) {
|
||||||
|
parts := strings.Split(line, " ")
|
||||||
|
if len(parts) > 2 {
|
||||||
|
instance.MountPoint = parts[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushCache 刷新缓存数据
|
||||||
|
func (m *OpenCASManager) FlushCache(id string) error {
|
||||||
|
m.logger.Infof("刷新缓存实例 %s 的数据", id)
|
||||||
|
_, err := utils.ExecuteCommand("casadm", "-F", "-i", id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("刷新缓存失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStats 获取缓存统计信息
|
||||||
|
func (m *OpenCASManager) GetStats(id string) (string, error) {
|
||||||
|
output, err := utils.ExecuteCommand("casadm", "-P", "-i", id, "--stats")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("获取缓存统计信息失败: %v", err)
|
||||||
|
}
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatDevice 格式化设备
|
||||||
|
func (m *OpenCASManager) FormatDevice(device, fsType string) error {
|
||||||
|
m.logger.Infof("格式化设备 %s 为 %s 文件系统", device, fsType)
|
||||||
|
_, err := utils.ExecuteCommand("mkfs", "-t", fsType, device)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("格式化设备失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MountDevice 挂载设备
|
||||||
|
func (m *OpenCASManager) MountDevice(device, mountPoint string) error {
|
||||||
|
m.logger.Infof("挂载设备 %s 到 %s", device, mountPoint)
|
||||||
|
|
||||||
|
// 确保挂载点存在
|
||||||
|
err := utils.CreateDirIfNotExist(mountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("创建挂载点失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行挂载
|
||||||
|
_, err = utils.ExecuteCommand("mount", device, mountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("挂载设备失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmountDevice 卸载设备
|
||||||
|
func (m *OpenCASManager) UnmountDevice(mountPoint string) error {
|
||||||
|
m.logger.Infof("卸载挂载点 %s", mountPoint)
|
||||||
|
_, err := utils.ExecuteCommand("umount", mountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("卸载设备失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulatePowerCut 模拟断电
|
||||||
|
func (m *OpenCASManager) SimulatePowerCut(id string) error {
|
||||||
|
m.logger.Warn("模拟断电,将强制停止缓存实例 %s", id)
|
||||||
|
|
||||||
|
// 获取缓存状态
|
||||||
|
instance, err := m.GetCacheStatus(id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取缓存状态失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已挂载,先卸载
|
||||||
|
if instance.Mounted && instance.MountPoint != "" {
|
||||||
|
err = m.UnmountDevice(instance.MountPoint)
|
||||||
|
if err != nil {
|
||||||
|
m.logger.Warn("卸载设备失败,继续强制停止: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制停止缓存,模拟断电
|
||||||
|
_, err = utils.ExecuteCommand("casadm", "-T", "-i", id, "-f")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("模拟断电失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.logger.Info("模拟断电完成")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepairCache 尝试修复损坏的缓存
|
||||||
|
func (m *OpenCASManager) RepairCache(id string, cacheDevice string) error {
|
||||||
|
m.logger.Info("尝试修复缓存实例 %s", id)
|
||||||
|
_, err := utils.ExecuteCommand("casadm", "-L", "-i", id, "-d", cacheDevice)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("修复缓存失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user