mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-12 17:46:20 +08:00
266 lines
8.3 KiB
Go
266 lines
8.3 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"sync"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
|
"github.com/1Panel-dev/1Panel/agent/app/model"
|
|
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
|
"github.com/1Panel-dev/1Panel/agent/global"
|
|
"github.com/jinzhu/copier"
|
|
)
|
|
|
|
type BackupRecordService struct{}
|
|
|
|
type IBackupRecordService interface {
|
|
SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error)
|
|
SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error)
|
|
DownloadRecord(info dto.DownloadRecord) (string, error)
|
|
DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error
|
|
BatchDeleteRecord(ids []uint) error
|
|
ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error)
|
|
|
|
ListFiles(req dto.OperateByID) []string
|
|
LoadRecordSize(req dto.SearchForSize) ([]dto.RecordFileSize, error)
|
|
}
|
|
|
|
func NewIBackupRecordService() IBackupRecordService {
|
|
return &BackupRecordService{}
|
|
}
|
|
|
|
func (u *BackupRecordService) SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error) {
|
|
total, records, err := backupRepo.PageRecord(
|
|
search.Page, search.PageSize,
|
|
repo.WithOrderBy("created_at desc"),
|
|
repo.WithByName(search.Name),
|
|
repo.WithByType(search.Type),
|
|
repo.WithByDetailName(search.DetailName),
|
|
)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
accounts, _ := backupRepo.List()
|
|
var data []dto.BackupRecords
|
|
for _, record := range records {
|
|
var item dto.BackupRecords
|
|
if err := copier.Copy(&item, &record); err != nil {
|
|
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
|
|
}
|
|
for _, account := range accounts {
|
|
if account.ID == record.DownloadAccountID {
|
|
item.DownloadAccountID = account.ID
|
|
item.AccountName = account.Name
|
|
item.AccountType = account.Type
|
|
break
|
|
}
|
|
}
|
|
data = append(data, item)
|
|
}
|
|
return total, data, err
|
|
}
|
|
|
|
func (u *BackupRecordService) SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) {
|
|
total, records, err := backupRepo.PageRecord(
|
|
search.Page, search.PageSize,
|
|
repo.WithOrderBy("created_at desc"),
|
|
backupRepo.WithByCronID(search.CronjobID),
|
|
)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
accounts, _ := backupRepo.List()
|
|
var data []dto.BackupRecords
|
|
for _, record := range records {
|
|
var item dto.BackupRecords
|
|
if err := copier.Copy(&item, &record); err != nil {
|
|
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
|
|
}
|
|
for _, account := range accounts {
|
|
if account.ID == record.DownloadAccountID {
|
|
item.DownloadAccountID = account.ID
|
|
item.AccountName = account.Name
|
|
item.AccountType = account.Type
|
|
break
|
|
}
|
|
}
|
|
data = append(data, item)
|
|
}
|
|
return total, data, err
|
|
}
|
|
|
|
func (u *BackupRecordService) DownloadRecord(info dto.DownloadRecord) (string, error) {
|
|
account, client, err := NewBackupClientWithID(info.DownloadAccountID)
|
|
if err != nil {
|
|
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
|
|
}
|
|
if account.Type == "LOCAL" {
|
|
return path.Join(global.Dir.LocalBackupDir, info.FileDir, info.FileName), nil
|
|
}
|
|
targetPath := fmt.Sprintf("%s/download/%s/%s", global.Dir.DataDir, info.FileDir, info.FileName)
|
|
if _, err := os.Stat(path.Dir(targetPath)); err != nil && os.IsNotExist(err) {
|
|
if err = os.MkdirAll(path.Dir(targetPath), os.ModePerm); err != nil {
|
|
global.LOG.Errorf("mkdir %s failed, err: %v", path.Dir(targetPath), err)
|
|
}
|
|
}
|
|
srcPath := fmt.Sprintf("%s/%s", info.FileDir, info.FileName)
|
|
if len(account.BackupPath) != 0 {
|
|
srcPath = path.Join(account.BackupPath, srcPath)
|
|
}
|
|
if exist, _ := client.Exist(srcPath); exist {
|
|
isOK, err := client.Download(srcPath, targetPath)
|
|
if !isOK {
|
|
return "", fmt.Errorf("cloud storage download failed, err: %v", err)
|
|
}
|
|
}
|
|
return targetPath, nil
|
|
}
|
|
|
|
func (u *BackupRecordService) DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error {
|
|
if !withDeleteFile {
|
|
return backupRepo.DeleteRecord(context.Background(), repo.WithByType(backupType), repo.WithByName(name), repo.WithByDetailName(detailName))
|
|
}
|
|
|
|
records, err := backupRepo.ListRecord(repo.WithByType(backupType), repo.WithByName(name), repo.WithByDetailName(detailName))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, record := range records {
|
|
_, client, err := NewBackupClientWithID(record.DownloadAccountID)
|
|
if err != nil {
|
|
global.LOG.Errorf("new client for backup account failed, err: %v", err)
|
|
continue
|
|
}
|
|
if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil {
|
|
global.LOG.Errorf("remove file %s failed, err: %v", path.Join(record.FileDir, record.FileName), err)
|
|
}
|
|
_ = backupRepo.DeleteRecord(context.Background(), repo.WithByID(record.ID))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (u *BackupRecordService) BatchDeleteRecord(ids []uint) error {
|
|
records, err := backupRepo.ListRecord(repo.WithByIDs(ids))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, record := range records {
|
|
_, client, err := NewBackupClientWithID(record.DownloadAccountID)
|
|
if err != nil {
|
|
global.LOG.Errorf("new client for backup account failed, err: %v", err)
|
|
continue
|
|
}
|
|
if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil {
|
|
global.LOG.Errorf("remove file %s failed, err: %v", path.Join(record.FileDir, record.FileName), err)
|
|
}
|
|
}
|
|
return backupRepo.DeleteRecord(context.Background(), repo.WithByIDs(ids))
|
|
}
|
|
|
|
func (u *BackupRecordService) ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) {
|
|
records, err := backupRepo.ListRecord(
|
|
repo.WithOrderBy("created_at asc"),
|
|
repo.WithByName(name),
|
|
repo.WithByType("app"),
|
|
backupRepo.WithFileNameStartWith(fileName),
|
|
backupRepo.WithByDetailName(detailName),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return records, err
|
|
}
|
|
|
|
func (u *BackupRecordService) ListFiles(req dto.OperateByID) []string {
|
|
var datas []string
|
|
_, client, err := NewBackupClientWithID(req.ID)
|
|
if err != nil {
|
|
return datas
|
|
}
|
|
prefix := "system_snapshot"
|
|
files, err := client.ListObjects(prefix)
|
|
if err != nil {
|
|
global.LOG.Debugf("load files failed, err: %v", err)
|
|
return datas
|
|
}
|
|
for _, file := range files {
|
|
if len(file) != 0 {
|
|
datas = append(datas, path.Base(file))
|
|
}
|
|
}
|
|
return datas
|
|
}
|
|
|
|
type backupSizeHelper struct {
|
|
ID uint `json:"id"`
|
|
DownloadID uint `json:"downloadID"`
|
|
FilePath string `json:"filePath"`
|
|
Size uint `json:"size"`
|
|
}
|
|
|
|
func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.RecordFileSize, error) {
|
|
var list []backupSizeHelper
|
|
switch req.Type {
|
|
case "snapshot":
|
|
_, records, err := snapshotRepo.Page(req.Page, req.PageSize, repo.WithByLikeName(req.Info))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, item := range records {
|
|
list = append(list, backupSizeHelper{ID: item.ID, DownloadID: item.DownloadAccountID, FilePath: fmt.Sprintf("system_snapshot/%s.tar.gz", item.Name)})
|
|
}
|
|
case "cronjob":
|
|
_, records, err := backupRepo.PageRecord(req.Page, req.PageSize, backupRepo.WithByCronID(req.CronjobID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, item := range records {
|
|
list = append(list, backupSizeHelper{ID: item.ID, DownloadID: item.DownloadAccountID, FilePath: path.Join(item.FileDir, item.FileName)})
|
|
}
|
|
default:
|
|
_, records, err := backupRepo.PageRecord(
|
|
req.Page, req.PageSize,
|
|
repo.WithOrderBy("created_at desc"),
|
|
repo.WithByName(req.Name),
|
|
repo.WithByType(req.Type),
|
|
repo.WithByDetailName(req.DetailName),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, item := range records {
|
|
list = append(list, backupSizeHelper{ID: item.ID, DownloadID: item.DownloadAccountID, FilePath: path.Join(item.FileDir, item.FileName)})
|
|
}
|
|
}
|
|
recordMap := make(map[uint]struct{})
|
|
var recordIds []string
|
|
for _, record := range list {
|
|
if _, ok := recordMap[record.DownloadID]; !ok {
|
|
recordMap[record.DownloadID] = struct{}{}
|
|
recordIds = append(recordIds, fmt.Sprintf("%v", record.DownloadID))
|
|
}
|
|
}
|
|
clientMap, err := NewBackupClientMap(recordIds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var datas []dto.RecordFileSize
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < len(list); i++ {
|
|
datas = append(datas, dto.RecordFileSize{ID: list[i].ID})
|
|
if val, ok := clientMap[fmt.Sprintf("%v", list[i].DownloadID)]; ok {
|
|
wg.Add(1)
|
|
go func(index int) {
|
|
datas[index].Size, _ = val.client.Size(path.Join(val.backupPath, list[i].FilePath))
|
|
wg.Done()
|
|
}(i)
|
|
}
|
|
}
|
|
wg.Wait()
|
|
return datas, nil
|
|
}
|