Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 53 additions & 6 deletions agent/app/service/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (
"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/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage"
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage/client"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
Expand Down Expand Up @@ -393,9 +395,13 @@ type backupClientHelper struct {
name string
backupPath string
client cloud_storage.CloudStorageClient

isOk bool
hasBackuped bool
message string
}

func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
func NewBackupClientMap(ids []string) map[string]backupClientHelper {
var accounts []model.BackupAccount
var idItems []uint
for i := 0; i < len(ids); i++ {
Expand All @@ -406,18 +412,59 @@ func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
clientMap := make(map[string]backupClientHelper)
for _, item := range accounts {
backClient, err := newClient(&item, true)
if err != nil {
return nil, err
}
clientMap[fmt.Sprintf("%v", item.ID)] = backupClientHelper{
itemHelper := backupClientHelper{
client: backClient,
name: item.Name,
backupPath: item.BackupPath,
accountType: item.Type,
id: item.ID,
isOk: err == nil,
}
if err != nil {
itemHelper.message = err.Error()
}
clientMap[fmt.Sprintf("%v", item.ID)] = itemHelper
}
return clientMap
}

func uploadWithMap(taskItem task.Task, accountMap map[string]backupClientHelper, src, dst, accountIDs string, downloadAccountID, retry uint) error {
accounts := strings.Split(accountIDs, ",")
for _, account := range accounts {
if len(account) == 0 {
continue
}
itemBackup, ok := accountMap[account]
if !ok {
continue
}
if itemBackup.hasBackuped {
continue
}
if !itemBackup.isOk {
taskItem.LogFailed(i18n.GetMsgWithDetail("LoadBackupFailed", itemBackup.message))
continue
}
taskItem.LogStart(i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
"file": path.Join(itemBackup.backupPath, dst),
"backup": itemBackup.name,
}))
for i := 0; i < int(retry); i++ {
_, err := itemBackup.client.Upload(src, path.Join(itemBackup.backupPath, dst))
taskItem.LogWithStatus(i18n.GetMsgByKey("Upload"), err)
if err != nil {
if account == fmt.Sprintf("%d", downloadAccountID) {
return err
}
} else {
break
}
}
itemBackup.hasBackuped = true
accountMap[account] = itemBackup
}
return clientMap, nil
os.RemoveAll(src)
return nil
}

func newClient(account *model.BackupAccount, isEncrypt bool) (cloud_storage.CloudStorageClient, error) {
Expand Down
5 changes: 1 addition & 4 deletions agent/app/service/backup_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,8 @@ func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.Recor
recordIds = append(recordIds, fmt.Sprintf("%v", record.DownloadID))
}
}
clientMap, err := NewBackupClientMap(recordIds)
if err != nil {
return nil, err
}

clientMap := NewBackupClientMap(recordIds)
var datas []dto.RecordFileSize
var wg sync.WaitGroup
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
Expand Down
5 changes: 1 addition & 4 deletions agent/app/service/cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,10 +497,7 @@ func (u *CronjobService) CleanRecord(req dto.CronjobClean) error {
}
if req.CleanData {
if hasBackup(cronjob.Type) {
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
}
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !req.CleanRemoteData {
for key := range accountMap {
if key != constant.Local {
Expand Down
91 changes: 47 additions & 44 deletions agent/app/service/cronjob_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
if len(apps) == 0 {
return errors.New("no such app in database!")
}
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
for _, app := range apps {
retry := 0
Expand All @@ -54,16 +54,18 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
return nil
}
}
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil {

src := path.Join(backupDir, record.FileName)
dst := strings.TrimPrefix(src, global.Dir.LocalBackupDir+"/tmp/")
if err := uploadWithMap(*task, accountMap, src, dst, cronjob.SourceAccountIDs, cronjob.DownloadAccountID, cronjob.RetryTimes); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
}
record.FileDir = path.Dir(downloadPath)
record.FileDir = path.Dir(dst)
if err := backupRepo.CreateRecord(&record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
Expand All @@ -80,9 +82,9 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
if len(webs) == 0 {
return errors.New("no such website in database!")
}
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
for _, web := range webs {
retry := 0
Expand All @@ -107,16 +109,17 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
}
}

downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil {
src := path.Join(backupDir, record.FileName)
dst := strings.TrimPrefix(src, global.Dir.LocalBackupDir+"/tmp/")
if err := uploadWithMap(*task, accountMap, src, dst, cronjob.SourceAccountIDs, cronjob.DownloadAccountID, cronjob.RetryTimes); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
}
record.FileDir = path.Dir(downloadPath)
record.FileDir = path.Dir(dst)
if err := backupRepo.CreateRecord(&record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
Expand All @@ -133,9 +136,9 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
if len(dbs) == 0 {
return errors.New("no such db in database!")
}
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
for _, dbInfo := range dbs {
retry := 0
Expand Down Expand Up @@ -173,16 +176,17 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
}
}

downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil {
src := path.Join(backupDir, record.FileName)
dst := strings.TrimPrefix(src, global.Dir.LocalBackupDir+"/tmp/")
if err := uploadWithMap(*task, accountMap, src, dst, cronjob.SourceAccountIDs, cronjob.DownloadAccountID, cronjob.RetryTimes); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
}
record.FileDir = path.Dir(downloadPath)
record.FileDir = path.Dir(dst)
if err := backupRepo.CreateRecord(&record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
Expand All @@ -195,11 +199,11 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
}

func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
taskItem.AddSubTaskWithOps(task.GetTaskName(cronjob.SourceDir, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
}
fileName := fmt.Sprintf("%s.tar.gz", startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(2))
if cronjob.IsDir || len(strings.Split(cronjob.SourceDir, ",")) == 1 {
fileName = loadFileName(cronjob.SourceDir)
Expand All @@ -226,15 +230,15 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
record.CronjobID = cronjob.ID
record.Name = cronjob.Name
record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, fileName))
if err != nil {
taskItem.LogFailedWithErr("Upload backup file", err)

src := path.Join(backupDir, fileName)
dst := strings.TrimPrefix(src, global.Dir.LocalBackupDir+"/tmp/")
if err := uploadWithMap(*task, accountMap, src, dst, cronjob.SourceAccountIDs, cronjob.DownloadAccountID, cronjob.RetryTimes); err != nil {
return err
}
record.FileDir = path.Dir(downloadPath)
record.FileDir = path.Dir(dst)
record.FileName = fileName
if err := backupRepo.CreateRecord(&record); err != nil {
taskItem.LogFailedWithErr("Save record", err)
return err
}
u.removeExpiredBackup(cronjob, accountMap, record)
Expand All @@ -244,11 +248,11 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
}

func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {
taskItem.AddSubTaskWithOps(task.GetTaskName(i18n.GetMsgByKey("BackupSystemLog"), task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
}
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
taskItem.AddSubTaskWithOps(task.GetTaskName(i18n.GetMsgByKey("SystemLog"), task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
nameItem := startTime.Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5)
fileName := fmt.Sprintf("system_log_%s.tar.gz", nameItem)
backupDir := path.Join(global.Dir.LocalBackupDir, "tmp/log", nameItem)
Expand All @@ -261,15 +265,15 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
record.CronjobID = cronjob.ID
record.Name = cronjob.Name
record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(path.Dir(backupDir), fileName))
if err != nil {
taskItem.LogFailedWithErr("Upload backup file", err)

src := path.Join(path.Dir(backupDir), fileName)
dst := strings.TrimPrefix(src, global.Dir.LocalBackupDir+"/tmp/")
if err := uploadWithMap(*task, accountMap, src, dst, cronjob.SourceAccountIDs, cronjob.DownloadAccountID, cronjob.RetryTimes); err != nil {
return err
}
record.FileDir = path.Dir(downloadPath)
record.FileDir = path.Dir(dst)
record.FileName = fileName
if err := backupRepo.CreateRecord(&record); err != nil {
taskItem.LogFailedWithErr("Save record", err)
return err
}
u.removeExpiredBackup(cronjob, accountMap, record)
Expand All @@ -279,11 +283,10 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
}

func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.JobRecords, taskItem *task.Task) error {
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}

var record model.BackupRecord
record.From = "cronjob"
record.Type = "snapshot"
Expand Down Expand Up @@ -461,6 +464,7 @@ func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret st
}
}
}
taskItem.Logf("%s Website logs...", i18n.GetMsgByKey("TaskBackup"))

systemDir := path.Join(targetDir, "system")
if _, err := os.Stat(systemDir); err != nil && os.IsNotExist(err) {
Expand All @@ -469,7 +473,6 @@ func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret st
}
}

taskItem.Logf("%s System logs...", i18n.GetMsgByKey("TaskBackup"))
systemLogFiles, _ := os.ReadDir(global.Dir.LogDir)
if len(systemLogFiles) != 0 {
for i := 0; i < len(systemLogFiles); i++ {
Expand All @@ -478,8 +481,8 @@ func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret st
}
}
}
taskItem.Logf("%s System logs...", i18n.GetMsgByKey("TaskBackup"))

taskItem.Logf("%s SSH logs...", i18n.GetMsgByKey("TaskBackup"))
loginLogFiles, _ := os.ReadDir("/var/log")
loginDir := path.Join(targetDir, "login")
if _, err := os.Stat(loginDir); err != nil && os.IsNotExist(err) {
Expand All @@ -494,7 +497,7 @@ func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret st
}
}
}
taskItem.Log("backup ssh log successful!")
taskItem.Logf("%s SSH logs...", i18n.GetMsgByKey("TaskBackup"))

if err := fileOp.TarGzCompressPro(true, targetDir, path.Join(path.Dir(targetDir), fileName), secret, ""); err != nil {
return err
Expand Down
Loading
Loading