fix: plp 输出展示错误
This commit is contained in:
parent
3c1cc26896
commit
a1c99352a8
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,7 +22,6 @@ mem.pprof
|
||||
# Go语言相关
|
||||
*.o
|
||||
*.a
|
||||
/pkg/
|
||||
/vendor/
|
||||
|
||||
# IDE和编辑器文件
|
||||
|
@ -196,7 +196,7 @@ func (c *Client) MonitorTestStatus(testID string) error {
|
||||
return
|
||||
case "integrity":
|
||||
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"])
|
||||
}
|
||||
}
|
||||
|
@ -487,11 +487,12 @@ func StartServer(cfg *config.Config, runner *TestRunner, logger *logrus.Logger)
|
||||
// 保存完整性信息
|
||||
runner.SaveIntegrityInfo(testID, integrityInfo)
|
||||
|
||||
// 发送完整性信息
|
||||
// 发送完整性信息 && BlocksMap 清理掉
|
||||
integrityInfo.BlocksMap = nil
|
||||
|
||||
runner.sendIntegrityUpdate(testID, "数据完整性检查完成", integrityInfo)
|
||||
|
||||
logger.Infof("恢复测试完成: 丢失数据: %.2f MB", integrityInfo.DataLossMB)
|
||||
logger.Infof("恢复测试完成: 没填充的数据: %.2f MB", integrityInfo.DataLossMB)
|
||||
} else {
|
||||
logger.Error("不是断电测试实例,无法执行数据完整性检查")
|
||||
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.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))
|
||||
|
||||
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