Skip to content

Commit

Permalink
feat: 快照回滚增加任务执行记录
Browse files Browse the repository at this point in the history
  • Loading branch information
ssonglius11 committed Sep 25, 2024
1 parent 5fc60b1 commit eb9b56e
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 76 deletions.
5 changes: 4 additions & 1 deletion agent/app/dto/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ type SnapshotImport struct {
type SnapshotInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
TaskID string `json:"taskID"`
Description string `json:"description" validate:"max=256"`
From string `json:"from"`
DefaultDownload string `json:"defaultDownload"`
Expand All @@ -90,6 +89,10 @@ type SnapshotInfo struct {
Version string `json:"version"`
Size int64 `json:"size"`

TaskID string `json:"taskID"`
TaskRecoverID string `json:"taskRecoverID"`
TaskRollbackID string `json:"taskRollbackID"`

InterruptStep string `json:"interruptStep"`
RecoverStatus string `json:"recoverStatus"`
RecoverMessage string `json:"recoverMessage"`
Expand Down
30 changes: 15 additions & 15 deletions agent/app/service/snapshot_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,47 +106,47 @@ func (u *SnapshotService) HandleSnapshot(req dto.SnapshotCreate) error {
_ = os.MkdirAll(baseDir, os.ModePerm)

go func() {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapDBInfo"),
taskItem.AddSubTaskWithAlias(
"SnapDBInfo",
func(t *task.Task) error { return loadDbConn(&itemHelper, rootDir, req) },
nil,
)

if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapBaseInfo" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapBaseInfo"),
taskItem.AddSubTaskWithAlias(
"SnapBaseInfo",
func(t *task.Task) error { return snapBaseData(itemHelper, baseDir) },
nil,
)
req.InterruptStep = ""
}
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapInstallApp" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapInstallApp"),
taskItem.AddSubTaskWithAlias(
"SnapInstallApp",
func(t *task.Task) error { return snapAppImage(itemHelper, req, rootDir) },
nil,
)
req.InterruptStep = ""
}
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapLocalBackup" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapLocalBackup"),
taskItem.AddSubTaskWithAlias(
"SnapLocalBackup",
func(t *task.Task) error { return snapBackupData(itemHelper, req, rootDir) },
nil,
)
req.InterruptStep = ""
}
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapPanelData" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapPanelData"),
taskItem.AddSubTaskWithAlias(
"SnapPanelData",
func(t *task.Task) error { return snapPanelData(itemHelper, req, rootDir) },
nil,
)
req.InterruptStep = ""
}

taskItem.AddSubTask(
i18n.GetMsgByKey("SnapCloseDBConn"),
"SnapCloseDBConn",
func(t *task.Task) error {
taskItem.Log("######################## 6 / 8 ########################")
closeDatabase(itemHelper.snapAgentDB)
Expand All @@ -156,16 +156,16 @@ func (u *SnapshotService) HandleSnapshot(req dto.SnapshotCreate) error {
nil,
)
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapCompress" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapCompress"),
taskItem.AddSubTaskWithAlias(
"SnapCompress",
func(t *task.Task) error { return snapCompress(itemHelper, rootDir, req.Secret) },
nil,
)
req.InterruptStep = ""
}
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapUpload" {
taskItem.AddSubTask(
i18n.GetMsgByKey("SnapUpload"),
taskItem.AddSubTaskWithAlias(
"SnapUpload",
func(t *task.Task) error {
return snapUpload(itemHelper, req.SourceAccountIDs, fmt.Sprintf("%s.tar.gz", rootDir))
},
Expand Down
51 changes: 27 additions & 24 deletions agent/app/service/snapshot_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
return errors.New(errInfo)
}
if len(snap.RollbackStatus) != 0 && snap.RollbackStatus != constant.StatusSuccess {
return fmt.Errorf("the snapshot has been rolled back and cannot be restored again")
req.IsNew = true
}
if !req.IsNew && (snap.InterruptStep == "RecoverDownload" || snap.InterruptStep == "RecoverDecompress" || snap.InterruptStep == "BackupBeforeRecover") {
req.IsNew = true
}
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"recover_status": constant.StatusWaiting})
_ = settingRepo.Update("SystemStatus", "Recovering")
Expand Down Expand Up @@ -69,16 +72,16 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
}()

if req.IsNew || snap.InterruptStep == "RecoverDownload" || req.ReDownload {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverDownload"),
taskItem.AddSubTaskWithAlias(
"RecoverDownload",
func(t *task.Task) error { return handleDownloadSnapshot(&itemHelper, snap, rootDir) },
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverDecompress" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverDecompress"),
taskItem.AddSubTaskWithAlias(
"RecoverDecompress",
func(t *task.Task) error {
itemHelper.Task.Log("######################## 2 / 10 ########################")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverDecompress", snap.Name))
Expand All @@ -91,77 +94,77 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "BackupBeforeRecover" {
taskItem.AddSubTask(
i18n.GetMsgByKey("BackupBeforeRecover"),
taskItem.AddSubTaskWithAlias(
"BackupBeforeRecover",
func(t *task.Task) error { return backupBeforeRecover(snap.Name, &itemHelper) },
nil,
)
req.IsNew = true
}

var snapJson SnapshotJson
taskItem.AddSubTask(
i18n.GetMsgByKey("Readjson"),
taskItem.AddSubTaskWithAlias(
"Readjson",
func(t *task.Task) error {
snapJson, err = readFromJson(path.Join(rootDir, snap.Name), &itemHelper)
return err
},
nil,
)
if req.IsNew || snap.InterruptStep == "RecoverApp" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverApp"),
taskItem.AddSubTaskWithAlias(
"RecoverApp",
func(t *task.Task) error { return recoverAppData(path.Join(rootDir, snap.Name), &itemHelper) },
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverBaseData" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverBaseData"),
taskItem.AddSubTaskWithAlias(
"RecoverBaseData",
func(t *task.Task) error { return recoverBaseData(path.Join(rootDir, snap.Name, "base"), &itemHelper) },
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverDBData" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverDBData"),
taskItem.AddSubTaskWithAlias(
"RecoverDBData",
func(t *task.Task) error { return recoverDBData(path.Join(rootDir, snap.Name, "db"), &itemHelper) },
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverBackups" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverBackups"),
taskItem.AddSubTaskWithAlias(
"RecoverBackups",
func(t *task.Task) error {
itemHelper.Task.Log("######################## 8 / 10 ########################")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverBackups", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_backup.tar.gz"), snapJson.BackupDataDir, "")
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Compress"), err)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
return err
},
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverPanelData" {
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverPanelData"),
taskItem.AddSubTaskWithAlias(
"RecoverPanelData",
func(t *task.Task) error {
itemHelper.Task.Log("######################## 9 / 10 ########################")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverPanelData", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel"), "")
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Compress"), err)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
return err
},
nil,
)
req.IsNew = true
}
taskItem.AddSubTask(
i18n.GetMsgByKey("RecoverDBData"),
taskItem.AddSubTaskWithAlias(
"RecoverDBData",
func(t *task.Task) error {
return restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose"), &itemHelper)
},
Expand All @@ -170,7 +173,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {

if err := taskItem.Execute(); err != nil {
_ = settingRepo.Update("SystemStatus", "Free")
_ = snapshotRepo.Update(req.ID, map[string]interface{}{"recover_status": constant.StatusFailed, "message": err.Error(), "interrupt_step": taskItem.Task.CurrentStep})
_ = snapshotRepo.Update(req.ID, map[string]interface{}{"recover_status": constant.StatusFailed, "recover_message": err.Error(), "interrupt_step": taskItem.Task.CurrentStep})
return
}
_ = os.RemoveAll(rootDir)
Expand Down
119 changes: 84 additions & 35 deletions agent/app/service/snapshot_rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import (
"path"

"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/task"
"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/files"
)

Expand All @@ -16,43 +19,89 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
if err != nil {
return err
}
go func() {
if err := handleRollback(snap.Name); err != nil {
global.LOG.Errorf("handle roll back snapshot failed, err: %v", err)
}
}()
return nil
}

func handleRollback(name string) error {
rootDir := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, name)
baseDir := path.Join(rootDir, "base")

FileOp := files.NewFileOp()
if err := FileOp.CopyDir(path.Join(rootDir, "1panel"), global.CONF.System.BaseDir); err != nil {
return err
}
if err := FileOp.CopyDir(path.Join(rootDir, "backup"), path.Dir(global.CONF.System.Backup)); err != nil {
return err
if len(snap.TaskRollbackID) != 0 {
req.TaskID = snap.TaskRollbackID
} else {
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"task_rollback_id": req.TaskID})
}
if err := FileOp.CopyFile(path.Join(baseDir, "1pctl"), "/usr/local/bin/1pctl"); err != nil {
return err
}
if err := FileOp.CopyFile(path.Join(baseDir, "1panel"), "/usr/local/bin/1panel"); err != nil {
return err
}
if err := FileOp.CopyFile(path.Join(baseDir, "1panel_agent"), "/usr/local/bin/1panel_agent"); err != nil {
return err
}
if err := FileOp.CopyFile(path.Join(baseDir, "1panel.service"), "/etc/systemd/system/1panel.service"); err != nil {
return err
}
if err := FileOp.CopyFile(path.Join(baseDir, "1panel_agent.service"), "/etc/systemd/system/1panel_agent.service"); err != nil {
return err
}
if err := FileOp.CopyFile(path.Join(baseDir, "daemon.json"), "/etc/docker/daemon.json"); err != nil {
taskItem, err := task.NewTaskWithOps(snap.Name, task.TaskRollback, task.TaskScopeSnapshot, req.TaskID, snap.ID)
if err != nil {
global.LOG.Errorf("new task for create snapshot failed, err: %v", err)
return err
}
_ = os.RemoveAll(rootDir)
go func() {
rootDir := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name)
baseDir := path.Join(rootDir, "base")

FileOp := files.NewFileOp()
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/usr/local/bin/1pctl"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1pctl"), "/usr/local/bin")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel"), "/usr/local/bin")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel_agent"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel_agent"), "/usr/local/bin")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel.service"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel.service"), "/etc/systemd/system")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel_agent.service"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel.service"), "/etc/systemd/system")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "daemon.json"), "/etc/docker")
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", global.CONF.System.Backup),
func(t *task.Task) error {
return FileOp.CopyDir(path.Join(rootDir, "backup"), global.CONF.System.Backup)
},
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", global.CONF.System.BaseDir),
func(t *task.Task) error {
return FileOp.CopyDir(path.Join(rootDir, "1panel"), global.CONF.System.BaseDir)
},
nil,
)
if err := taskItem.Execute(); err != nil {
_ = snapshotRepo.Update(req.ID, map[string]interface{}{"rollback_status": constant.StatusFailed, "rollback_message": err.Error()})
return
}
_ = snapshotRepo.Update(req.ID, map[string]interface{}{
"recover_status": "",
"recover_message": "",
"rollback_status": "",
"rollback_message": "",
"interrupt_step": "",
})
_ = os.RemoveAll(rootDir)
}()
return nil
}
Loading

0 comments on commit eb9b56e

Please sign in to comment.