From e359e1c5444f2ae124b5099bae697ba4c6e2688d Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Tue, 8 Oct 2024 21:58:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BF=AB=E7=85=A7=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=BC=82=E6=AD=A5=E8=8E=B7=E5=8F=96=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F=20(#6653)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #6540 --- agent/app/api/v2/snapshot.go | 22 ++++ agent/app/dto/snapshot.go | 8 ++ agent/app/service/backup.go | 1 + agent/app/service/snapshot.go | 100 ++++++++++-------- agent/router/ro_setting.go | 1 + frontend/src/api/interface/setting.ts | 7 ++ frontend/src/api/modules/setting.ts | 3 + frontend/src/views/setting/snapshot/index.vue | 100 +++++++++++++----- 8 files changed, 171 insertions(+), 71 deletions(-) diff --git a/agent/app/api/v2/snapshot.go b/agent/app/api/v2/snapshot.go index 8bca5bf5b..1520cfffd 100644 --- a/agent/app/api/v2/snapshot.go +++ b/agent/app/api/v2/snapshot.go @@ -135,6 +135,28 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) { }) } +// @Tags System Setting +// @Summary Load system snapshot size +// @Description 获取系统快照文件大小 +// @Accept json +// @Param request body dto.SearchWithPage true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /settings/snapshot/size [post] +func (b *BaseApi) LoadSnapshotSize(c *gin.Context) { + var req dto.SearchWithPage + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + accounts, err := snapshotService.LoadSize(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, accounts) +} + // @Tags System Setting // @Summary Recover system backup // @Description 从系统快照恢复 diff --git a/agent/app/dto/snapshot.go b/agent/app/dto/snapshot.go index a2e85d503..d4b928d95 100644 --- a/agent/app/dto/snapshot.go +++ b/agent/app/dto/snapshot.go @@ -101,3 +101,11 @@ type SnapshotInfo struct { RollbackMessage string `json:"rollbackMessage"` LastRollbackedAt string `json:"lastRollbackedAt"` } + +type SnapshotFile struct { + ID uint `json:"id"` + Name string `json:"name"` + From string `json:"from"` + DefaultDownload string `json:"defaultDownload"` + Size int64 `json:"size"` +} diff --git a/agent/app/service/backup.go b/agent/app/service/backup.go index 7c4a2f703..162c59f52 100644 --- a/agent/app/service/backup.go +++ b/agent/app/service/backup.go @@ -120,6 +120,7 @@ func (u *BackupService) CheckUsed(id uint) error { type loadSizeHelper struct { isOk bool + backupName string backupPath string client cloud_storage.CloudStorageClient } diff --git a/agent/app/service/snapshot.go b/agent/app/service/snapshot.go index ef97bac5e..6fd966e3a 100644 --- a/agent/app/service/snapshot.go +++ b/agent/app/service/snapshot.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path" + "strconv" "strings" "sync" @@ -18,7 +19,6 @@ import ( "github.com/docker/docker/api/types/image" "github.com/google/uuid" "github.com/jinzhu/copier" - "github.com/pkg/errors" "github.com/shirou/gopsutil/v3/host" ) @@ -28,6 +28,7 @@ type SnapshotService struct { type ISnapshotService interface { SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) + LoadSize(req dto.SearchWithPage) ([]dto.SnapshotFile, error) LoadSnapshotData() (dto.SnapshotData, error) SnapshotCreate(req dto.SnapshotCreate) error SnapshotReCreate(id uint) error @@ -46,15 +47,64 @@ func NewISnapshotService() ISnapshotService { } func (u *SnapshotService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) { - total, systemBackups, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithByLikeName(req.Info)) + total, records, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithByLikeName(req.Info)) if err != nil { return 0, nil, err } - dtoSnap, err := loadSnapSize(systemBackups) - if err != nil { - return 0, nil, err + var datas []dto.SnapshotInfo + for i := 0; i < len(records); i++ { + var item dto.SnapshotInfo + if err := copier.Copy(&item, &records[i]); err != nil { + return 0, nil, err + } + datas = append(datas, item) } - return total, dtoSnap, err + return total, datas, err +} + +func (u *SnapshotService) LoadSize(req dto.SearchWithPage) ([]dto.SnapshotFile, error) { + _, records, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithByLikeName(req.Info)) + if err != nil { + return nil, err + } + var datas []dto.SnapshotFile + var wg sync.WaitGroup + clientMap := make(map[uint]loadSizeHelper) + for i := 0; i < len(records); i++ { + itemPath := fmt.Sprintf("system_snapshot/%s.tar.gz", records[i].Name) + data := dto.SnapshotFile{ID: records[i].ID, Name: records[i].Name} + accounts := strings.Split(records[i].SourceAccountIDs, ",") + var accountNames []string + for _, account := range accounts { + itemVal, _ := strconv.Atoi(account) + if _, ok := clientMap[uint(itemVal)]; !ok { + backup, client, err := NewBackupClientWithID(uint(itemVal)) + if err != nil { + global.LOG.Errorf("load backup client from db failed, err: %v", err) + clientMap[records[i].DownloadAccountID] = loadSizeHelper{} + continue + } + backupName := fmt.Sprintf("%s - %s", backup.Type, backup.Name) + clientMap[uint(itemVal)] = loadSizeHelper{backupPath: strings.TrimLeft(backup.BackupPath, "/"), client: client, isOk: true, backupName: backupName} + accountNames = append(accountNames, backupName) + } + } + data.DefaultDownload = clientMap[records[i].DownloadAccountID].backupName + data.From = strings.Join(accountNames, ",") + if clientMap[records[i].DownloadAccountID].isOk { + wg.Add(1) + go func(index int) { + data.Size, _ = clientMap[records[index].DownloadAccountID].client.Size(path.Join(clientMap[records[index].DownloadAccountID].backupPath, itemPath)) + datas = append(datas, data) + wg.Done() + }(i) + } else { + datas = append(datas, data) + } + } + wg.Wait() + + return datas, nil } func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error { @@ -175,44 +225,6 @@ func loadOs() string { } } -func loadSnapSize(records []model.Snapshot) ([]dto.SnapshotInfo, error) { - var datas []dto.SnapshotInfo - clientMap := make(map[uint]loadSizeHelper) - var wg sync.WaitGroup - for i := 0; i < len(records); i++ { - var item dto.SnapshotInfo - if err := copier.Copy(&item, &records[i]); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - itemPath := fmt.Sprintf("system_snapshot/%s.tar.gz", item.Name) - if _, ok := clientMap[records[i].DownloadAccountID]; !ok { - backup, client, err := NewBackupClientWithID(records[i].DownloadAccountID) - if err != nil { - global.LOG.Errorf("load backup client from db failed, err: %v", err) - clientMap[records[i].DownloadAccountID] = loadSizeHelper{} - datas = append(datas, item) - continue - } - item.Size, _ = client.Size(path.Join(strings.TrimLeft(backup.BackupPath, "/"), itemPath)) - datas = append(datas, item) - clientMap[records[i].DownloadAccountID] = loadSizeHelper{backupPath: strings.TrimLeft(backup.BackupPath, "/"), client: client, isOk: true} - continue - } - if clientMap[records[i].DownloadAccountID].isOk { - wg.Add(1) - go func(index int) { - item.Size, _ = clientMap[records[index].DownloadAccountID].client.Size(path.Join(clientMap[records[index].DownloadAccountID].backupPath, itemPath)) - datas = append(datas, item) - wg.Done() - }(i) - } else { - datas = append(datas, item) - } - } - wg.Wait() - return datas, nil -} - func loadApps(fileOp fileUtils.FileOp) ([]dto.DataTree, error) { var data []dto.DataTree apps, err := appInstallRepo.ListBy() diff --git a/agent/router/ro_setting.go b/agent/router/ro_setting.go index 9d2524bad..1247b3dcc 100644 --- a/agent/router/ro_setting.go +++ b/agent/router/ro_setting.go @@ -19,6 +19,7 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) { settingRouter.POST("/snapshot", baseApi.CreateSnapshot) settingRouter.POST("/snapshot/recreate", baseApi.RecreateSnapshot) settingRouter.POST("/snapshot/search", baseApi.SearchSnapshot) + settingRouter.POST("/snapshot/size", baseApi.LoadSnapshotSize) settingRouter.POST("/snapshot/import", baseApi.ImportSnapshot) settingRouter.POST("/snapshot/del", baseApi.DeleteSnapshot) settingRouter.POST("/snapshot/recover", baseApi.RecoverSnapshot) diff --git a/frontend/src/api/interface/setting.ts b/frontend/src/api/interface/setting.ts index ffb9d87a1..b8a4aae98 100644 --- a/frontend/src/api/interface/setting.ts +++ b/frontend/src/api/interface/setting.ts @@ -166,6 +166,13 @@ export namespace Setting { rollbackStatus: string; rollbackMessage: string; } + export interface SnapshotFile { + id: number; + name: string; + from: string; + defaultDownload: string; + size: number; + } export interface SnapshotData { appData: Array; panelData: Array; diff --git a/frontend/src/api/modules/setting.ts b/frontend/src/api/modules/setting.ts index d4805b451..aa0e0d33f 100644 --- a/frontend/src/api/modules/setting.ts +++ b/frontend/src/api/modules/setting.ts @@ -124,6 +124,9 @@ export const snapshotRollback = (param: Setting.SnapshotRecover) => { export const searchSnapshotPage = (param: SearchWithPage) => { return http.post>(`/settings/snapshot/search`, param); }; +export const loadSnapshotSize = (param: SearchWithPage) => { + return http.post>(`/settings/snapshot/size`, param); +}; // upgrade export const loadUpgradeInfo = () => { diff --git a/frontend/src/views/setting/snapshot/index.vue b/frontend/src/views/setting/snapshot/index.vue index 329c15e2a..c533ab74c 100644 --- a/frontend/src/views/setting/snapshot/index.vue +++ b/frontend/src/views/setting/snapshot/index.vue @@ -38,41 +38,51 @@ @@ -168,6 +178,7 @@