270 lines
7.4 KiB
Go
270 lines
7.4 KiB
Go
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
|
|
}
|