初始化
This commit is contained in:
168
server/service/storage_test_service.go
Normal file
168
server/service/storage_test_service.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"seeyon-filesystem/config"
|
||||
"seeyon-filesystem/model"
|
||||
"seeyon-filesystem/storage"
|
||||
)
|
||||
|
||||
// StorageTestService 存储连通性测试服务
|
||||
type StorageTestService struct{}
|
||||
|
||||
func NewStorageTestService() *StorageTestService {
|
||||
return &StorageTestService{}
|
||||
}
|
||||
|
||||
// TestResult 测试结果
|
||||
type TestResult struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Latency int64 `json:"latency_ms"` // 耗时毫秒
|
||||
Detail string `json:"detail,omitempty"`
|
||||
}
|
||||
|
||||
// TestPolicy 测试存储策略连通性
|
||||
func (s *StorageTestService) TestPolicy(policyID uint64) (*TestResult, error) {
|
||||
var policy model.StoragePolicy
|
||||
if err := config.DB.First(&policy, policyID).Error; err != nil {
|
||||
return nil, fmt.Errorf("存储策略不存在")
|
||||
}
|
||||
|
||||
switch policy.Type {
|
||||
case "local":
|
||||
return s.testLocal(policy), nil
|
||||
case "minio":
|
||||
return s.testMinIO(policy), nil
|
||||
default:
|
||||
return &TestResult{Success: false, Message: "不支持的存储类型"}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewPolicy 测试新配置(未保存)
|
||||
func (s *StorageTestService) TestNewPolicy(policyType string, cfg model.PolicyConfig) *TestResult {
|
||||
switch policyType {
|
||||
case "local":
|
||||
return s.testLocalConfig(cfg)
|
||||
case "minio":
|
||||
return s.testMinIOConfig(cfg)
|
||||
default:
|
||||
return &TestResult{Success: false, Message: "不支持的存储类型"}
|
||||
}
|
||||
}
|
||||
|
||||
// testLocal 测试本地存储
|
||||
func (s *StorageTestService) testLocal(policy model.StoragePolicy) *TestResult {
|
||||
return s.testLocalConfig(policy.Config)
|
||||
}
|
||||
|
||||
func (s *StorageTestService) testLocalConfig(cfg model.PolicyConfig) *TestResult {
|
||||
start := time.Now()
|
||||
|
||||
basePath := cfg.BasePath
|
||||
if basePath == "" {
|
||||
return &TestResult{Success: false, Message: "未配置存储路径"}
|
||||
}
|
||||
|
||||
// 检查目录是否存在
|
||||
info, err := os.Stat(basePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// 尝试创建
|
||||
if err := os.MkdirAll(basePath, 0755); err != nil {
|
||||
return &TestResult{Success: false, Message: "目录不存在且无法创建: " + err.Error()}
|
||||
}
|
||||
return &TestResult{Success: true, Message: "目录已自动创建", Latency: time.Since(start).Milliseconds(), Detail: basePath}
|
||||
}
|
||||
return &TestResult{Success: false, Message: "访问目录失败: " + err.Error()}
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
return &TestResult{Success: false, Message: "路径不是目录"}
|
||||
}
|
||||
|
||||
// 测试写入权限
|
||||
testFile := basePath + "/.connectivity_test"
|
||||
if err := os.WriteFile(testFile, []byte("test"), 0644); err != nil {
|
||||
return &TestResult{Success: false, Message: "目录无写入权限: " + err.Error()}
|
||||
}
|
||||
os.Remove(testFile)
|
||||
|
||||
return &TestResult{
|
||||
Success: true,
|
||||
Message: "连接成功, 目录可读写",
|
||||
Latency: time.Since(start).Milliseconds(),
|
||||
Detail: basePath,
|
||||
}
|
||||
}
|
||||
|
||||
// testMinIO 测试MinIO连接
|
||||
func (s *StorageTestService) testMinIO(policy model.StoragePolicy) *TestResult {
|
||||
return s.testMinIOConfig(policy.Config)
|
||||
}
|
||||
|
||||
func (s *StorageTestService) testMinIOConfig(cfg model.PolicyConfig) *TestResult {
|
||||
start := time.Now()
|
||||
|
||||
if cfg.Endpoint == "" {
|
||||
return &TestResult{Success: false, Message: "未配置Endpoint"}
|
||||
}
|
||||
if cfg.Bucket == "" {
|
||||
return &TestResult{Success: false, Message: "未配置Bucket"}
|
||||
}
|
||||
|
||||
// AccessKey/SecretKey 可选(公开桶不需要)
|
||||
engine, err := storage.NewMinIOEngine(cfg.Endpoint, cfg.AccessKey, cfg.SecretKey, cfg.Bucket, cfg.UseSSL)
|
||||
if err != nil {
|
||||
return &TestResult{
|
||||
Success: false,
|
||||
Message: "连接失败: " + err.Error(),
|
||||
Latency: time.Since(start).Milliseconds(),
|
||||
}
|
||||
}
|
||||
|
||||
// 测试上传和下载
|
||||
testKey := ".connectivity_test"
|
||||
testContent := []byte("minio connectivity test")
|
||||
if err := engine.Upload(testKey, bytesReader(testContent), int64(len(testContent))); err != nil {
|
||||
return &TestResult{
|
||||
Success: false,
|
||||
Message: "上传测试失败: " + err.Error(),
|
||||
Latency: time.Since(start).Milliseconds(),
|
||||
}
|
||||
}
|
||||
|
||||
// 清理测试文件
|
||||
engine.Delete(testKey)
|
||||
|
||||
latency := time.Since(start).Milliseconds()
|
||||
return &TestResult{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("连接成功, Bucket=%s, 延迟=%dms", cfg.Bucket, latency),
|
||||
Latency: latency,
|
||||
Detail: fmt.Sprintf("%s/%s", cfg.Endpoint, cfg.Bucket),
|
||||
}
|
||||
}
|
||||
|
||||
// bytesReader 创建bytes.Reader
|
||||
func bytesReader(b []byte) *bytesReaderWrapper {
|
||||
return &bytesReaderWrapper{data: b, offset: 0}
|
||||
}
|
||||
|
||||
type bytesReaderWrapper struct {
|
||||
data []byte
|
||||
offset int
|
||||
}
|
||||
|
||||
func (r *bytesReaderWrapper) Read(p []byte) (int, error) {
|
||||
if r.offset >= len(r.data) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n := copy(p, r.data[r.offset:])
|
||||
r.offset += n
|
||||
return n, nil
|
||||
}
|
||||
Reference in New Issue
Block a user