mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-23 18:49:21 +08:00
feat(system-upgrade): Added support for multi-host upgrade
Some checks failed
sync2gitee / repo-sync (push) Has been cancelled
Some checks failed
sync2gitee / repo-sync (push) Has been cancelled
This commit is contained in:
parent
b6641b2776
commit
5a532b3418
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,8 +4,8 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
build/1panel_agent
|
||||
build/1panel_core
|
||||
build/1panel-agent
|
||||
build/1panel-core
|
||||
|
||||
# Mac
|
||||
.DS_Store
|
||||
|
4
Makefile
4
Makefile
@ -10,11 +10,11 @@ WEB_PATH=$(BASE_PAH)/frontend
|
||||
ASSERT_PATH= $(BASE_PAH)/core/cmd/server/web/assets
|
||||
|
||||
CORE_MAIN= $(BASE_PAH)/cmd/server/main.go
|
||||
CORE_NAME=1panel_core
|
||||
CORE_NAME=1panel-core
|
||||
|
||||
AGENT_PATH=$(BASE_PAH)/agent
|
||||
AGENT_MAIN= $(AGENT_PATH)/cmd/server/main.go
|
||||
AGENT_NAME=1panel_agent
|
||||
AGENT_NAME=1panel-agent
|
||||
|
||||
|
||||
clean_assets:
|
||||
|
@ -64,4 +64,6 @@ var (
|
||||
|
||||
websiteCAService = service.NewIWebsiteCAService()
|
||||
taskService = service.NewITaskService()
|
||||
|
||||
upgradeService = service.NewIUpgradeService()
|
||||
)
|
||||
|
33
agent/app/api/v2/upgrade.go
Normal file
33
agent/app/api/v2/upgrade.go
Normal file
@ -0,0 +1,33 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (b *BaseApi) Upgrade(c *gin.Context) {
|
||||
var req dto.Upgrade
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := upgradeService.Upgrade(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) Rollback(c *gin.Context) {
|
||||
var req dto.Rollback
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := upgradeService.Rollback(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
10
agent/app/dto/upgrade.go
Normal file
10
agent/app/dto/upgrade.go
Normal file
@ -0,0 +1,10 @@
|
||||
package dto
|
||||
|
||||
type Upgrade struct {
|
||||
Version string `json:"version"`
|
||||
UpgradePath string `json:"upgradePath"`
|
||||
}
|
||||
|
||||
type Rollback struct {
|
||||
Version string `json:"version"`
|
||||
}
|
@ -148,7 +148,7 @@ func (u *SnapshotService) HandleSnapshot(req dto.SnapshotCreate) error {
|
||||
taskItem.AddSubTask(
|
||||
"SnapCloseDBConn",
|
||||
func(t *task.Task) error {
|
||||
taskItem.Log("######################## 6 / 8 ########################")
|
||||
taskItem.Log("---------------------- 6 / 8 ----------------------")
|
||||
closeDatabase(itemHelper.snapAgentDB)
|
||||
closeDatabase(itemHelper.snapCoreDB)
|
||||
return nil
|
||||
@ -194,7 +194,7 @@ type snapHelper struct {
|
||||
}
|
||||
|
||||
func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) error {
|
||||
snap.Task.Log("######################## 1 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 1 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapDBInfo"))
|
||||
pathDB := path.Join(global.CONF.System.BaseDir, "1panel/db")
|
||||
|
||||
@ -246,17 +246,17 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
|
||||
}
|
||||
|
||||
func snapBaseData(snap snapHelper, targetDir string) error {
|
||||
snap.Task.Log("######################## 2 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 2 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
|
||||
|
||||
err := common.CopyFile("/usr/local/bin/1panel", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel"), err)
|
||||
err := common.CopyFile("/usr/local/bin/1panel-core", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-core"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.CopyFile("/usr/local/bin/1panel_agent", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel_agent"), err)
|
||||
err = common.CopyFile("/usr/local/bin/1panel-agent", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-agent"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -273,8 +273,8 @@ func snapBaseData(snap snapHelper, targetDir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.CopyFile("/etc/systemd/system/1panel_agent.service", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel_agent.service"), err)
|
||||
err = common.CopyFile("/etc/systemd/system/1panel-agent.service", targetDir)
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -301,7 +301,7 @@ func snapBaseData(snap snapHelper, targetDir string) error {
|
||||
}
|
||||
|
||||
func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) error {
|
||||
snap.Task.Log("######################## 3 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 3 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapInstallApp"))
|
||||
|
||||
var imageList []string
|
||||
@ -333,7 +333,7 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
|
||||
}
|
||||
|
||||
func snapBackupData(snap snapHelper, req dto.SnapshotCreate, targetDir string) error {
|
||||
snap.Task.Log("######################## 4 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 4 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapLocalBackup"))
|
||||
|
||||
excludes := loadBackupExcludes(snap, req.BackupData)
|
||||
@ -389,7 +389,7 @@ func loadAppBackupExcludes(req []dto.DataTree) []string {
|
||||
}
|
||||
|
||||
func snapPanelData(snap snapHelper, req dto.SnapshotCreate, targetDir string) error {
|
||||
snap.Task.Log("######################## 5 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 5 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapPanelData"))
|
||||
|
||||
excludes := loadPanelExcludes(req.PanelData)
|
||||
@ -447,7 +447,7 @@ func loadPanelExcludes(req []dto.DataTree) []string {
|
||||
}
|
||||
|
||||
func snapCompress(snap snapHelper, rootDir string, secret string) error {
|
||||
snap.Task.Log("######################## 7 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 7 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapCompress"))
|
||||
|
||||
tmpDir := path.Join(global.CONF.System.TmpDir, "system")
|
||||
@ -471,7 +471,7 @@ func snapCompress(snap snapHelper, rootDir string, secret string) error {
|
||||
}
|
||||
|
||||
func snapUpload(snap snapHelper, accounts string, file string) error {
|
||||
snap.Task.Log("######################## 8 / 8 ########################")
|
||||
snap.Task.Log("---------------------- 8 / 8 ----------------------")
|
||||
snap.Task.LogStart(i18n.GetMsgByKey("SnapUpload"))
|
||||
|
||||
source := path.Join(global.CONF.System.TmpDir, "system", path.Base(file))
|
||||
|
@ -83,7 +83,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
taskItem.AddSubTaskWithAlias(
|
||||
"RecoverDecompress",
|
||||
func(t *task.Task) error {
|
||||
itemHelper.Task.Log("######################## 2 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 2 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetWithName("RecoverDecompress", snap.Name))
|
||||
err := itemHelper.FileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.tar.gz", rootDir, snap.Name), rootDir, req.Secret)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
|
||||
@ -139,7 +139,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
taskItem.AddSubTaskWithAlias(
|
||||
"RecoverBackups",
|
||||
func(t *task.Task) error {
|
||||
itemHelper.Task.Log("######################## 8 / 10 ########################")
|
||||
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("Decompress"), err)
|
||||
@ -153,7 +153,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
taskItem.AddSubTaskWithAlias(
|
||||
"RecoverPanelData",
|
||||
func(t *task.Task) error {
|
||||
itemHelper.Task.Log("######################## 9 / 10 ########################")
|
||||
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("Decompress"), err)
|
||||
@ -183,7 +183,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
}
|
||||
|
||||
func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot, targetDir string) error {
|
||||
itemHelper.Task.Log("######################## 1 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 1 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDownload"))
|
||||
|
||||
account, client, err := NewBackupClientWithID(snap.DownloadAccountID)
|
||||
@ -200,7 +200,7 @@ func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot,
|
||||
}
|
||||
|
||||
func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("######################## 3 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 3 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("BackupBeforeRecover"))
|
||||
|
||||
rootDir := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, name)
|
||||
@ -224,13 +224,13 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = itemHelper.FileOp.CopyFile("/usr/local/bin/1panel", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel"), err)
|
||||
err = itemHelper.FileOp.CopyFile("/usr/local/bin/1panel-core", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-core"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = itemHelper.FileOp.CopyFile("/usr/local/bin/1panel_agent", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel_agent"), err)
|
||||
err = itemHelper.FileOp.CopyFile("/usr/local/bin/1panel-agent", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-agent"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -239,8 +239,8 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = itemHelper.FileOp.CopyFile("/etc/systemd/system/1panel_agent.service", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel_agent.service"), err)
|
||||
err = itemHelper.FileOp.CopyFile("/etc/systemd/system/1panel-agent.service", baseDir)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -253,7 +253,7 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
|
||||
func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) {
|
||||
itemHelper.Task.Log("######################## 4 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 4 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("Readjson"))
|
||||
|
||||
snapJsonPath := path.Join(rootDir, "base/snapshot.json")
|
||||
@ -277,7 +277,7 @@ func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson,
|
||||
}
|
||||
|
||||
func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("######################## 5 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 5 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverApp"))
|
||||
|
||||
if _, err := os.Stat(path.Join(src, "images.tar.gz")); err != nil {
|
||||
@ -325,7 +325,7 @@ func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
|
||||
func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("######################## 6 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 6 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
|
||||
|
||||
err := itemHelper.FileOp.CopyFile(path.Join(src, "1pctl"), "/usr/local/bin")
|
||||
@ -335,12 +335,12 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
|
||||
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel"), "/usr/local/bin")
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel"), err)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-core"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel_agent"), "/usr/local/bin")
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel_agent"), err)
|
||||
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel-agent"), "/usr/local/bin")
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-agent"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -349,8 +349,8 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel_agent.service"), "/etc/systemd/system")
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel_agent.service"), err)
|
||||
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel-agent.service"), "/etc/systemd/system")
|
||||
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -375,7 +375,7 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
|
||||
func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("######################## 7 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 7 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData"))
|
||||
err := itemHelper.FileOp.CopyDirWithExclude(src, path.Join(global.CONF.System.BaseDir, "1panel"), nil)
|
||||
|
||||
@ -384,7 +384,7 @@ func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
|
||||
func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("######################## 10 / 10 ########################")
|
||||
itemHelper.Task.Log("---------------------- 10 / 10 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose"))
|
||||
|
||||
composes, err := composeRepo.ListRecord()
|
||||
|
@ -42,16 +42,16 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
|
||||
nil,
|
||||
)
|
||||
taskItem.AddSubTask(
|
||||
i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel"),
|
||||
i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-core"),
|
||||
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"),
|
||||
i18n.GetWithName("SnapCopy", "/usr/local/bin/1panel-agent"),
|
||||
func(t *task.Task) error {
|
||||
return FileOp.CopyFile(path.Join(baseDir, "1panel_agent"), "/usr/local/bin")
|
||||
return FileOp.CopyFile(path.Join(baseDir, "1panel-agent"), "/usr/local/bin")
|
||||
},
|
||||
nil,
|
||||
)
|
||||
@ -63,7 +63,7 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
|
||||
nil,
|
||||
)
|
||||
taskItem.AddSubTask(
|
||||
i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel_agent.service"),
|
||||
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")
|
||||
},
|
||||
|
126
agent/app/service/upgrade.go
Normal file
126
agent/app/service/upgrade.go
Normal file
@ -0,0 +1,126 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
)
|
||||
|
||||
type UpgradeService struct{}
|
||||
|
||||
type IUpgradeService interface {
|
||||
Upgrade(req dto.Upgrade) error
|
||||
Rollback(req dto.Rollback) error
|
||||
}
|
||||
|
||||
func NewIUpgradeService() IUpgradeService {
|
||||
return &UpgradeService{}
|
||||
}
|
||||
|
||||
func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
fileOP := files.NewFileOp()
|
||||
if !fileOP.Stat(req.UpgradePath) {
|
||||
global.LOG.Errorf("handle upgrade 1panel to %s failed, err: no such file %s", req.Version, req.UpgradePath)
|
||||
return fmt.Errorf("no such upgrade file %s", req.UpgradePath)
|
||||
}
|
||||
|
||||
_, _ = cmd.Execf("rm -rf %s", path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", req.Version, "upgrade_*"))
|
||||
|
||||
backupDir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", req.Version, fmt.Sprintf("upgrade_%s", time.Now().Format(constant.DateTimeSlimLayout)))
|
||||
_ = os.MkdirAll(backupDir, os.ModePerm)
|
||||
if err := u.handleBackup(backupDir, fileOP); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOP.CopyFile(path.Join(req.UpgradePath, "1panel-agent.service"), "/etc/systemd/system/1panel-agent.service"); err != nil {
|
||||
_ = u.handleRollback(backupDir, 1, fileOP)
|
||||
global.LOG.Errorf("handle upgrade 1panel service file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := fileOP.CopyFile(path.Join(req.UpgradePath, "1panel-agent"), "/usr/local/bin"); err != nil {
|
||||
_ = u.handleRollback(backupDir, 2, fileOP)
|
||||
global.LOG.Errorf("handle upgrade 1panel failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("upgrade successful!")
|
||||
_ = settingRepo.Update("SystemVersion", req.Version)
|
||||
_, _ = cmd.ExecWithTimeOut("systemctl daemon-reload && systemctl restart 1panel.service", 1*time.Minute)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UpgradeService) Rollback(req dto.Rollback) error {
|
||||
rollbackDir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", req.Version)
|
||||
pathItem := loadRestorePath(rollbackDir)
|
||||
if len(pathItem) == 0 {
|
||||
return fmt.Errorf("no such rollback file in %s", rollbackDir)
|
||||
}
|
||||
fileOP := files.NewFileOp()
|
||||
return u.handleRollback(pathItem, 2, fileOP)
|
||||
}
|
||||
|
||||
func (u *UpgradeService) handleBackup(backupDir string, fileOP files.FileOp) error {
|
||||
if err := fileOP.CopyDir(path.Join(global.CONF.System.BaseDir, "1panel/db"), backupDir); err != nil {
|
||||
global.LOG.Errorf("handle backup original db file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := fileOP.CopyFile("/usr/local/bin/1panel-agent", backupDir); err != nil {
|
||||
global.LOG.Errorf("handle backup 1panel binary file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := fileOP.CopyFile("/etc/systemd/system/1panel-agent.service", backupDir); err != nil {
|
||||
global.LOG.Errorf("handle backup 1panel service file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UpgradeService) handleRollback(backupDir string, errStep int, fileOP files.FileOp) error {
|
||||
if errStep == 1 {
|
||||
if err := fileOP.CopyFile(path.Join(backupDir, "1panel-agent.service"), "/etc/systemd/system/1panel-agent.service"); err != nil {
|
||||
global.LOG.Errorf("handle recover 1panel service file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if errStep == 2 {
|
||||
if err := fileOP.CopyFile(path.Join(backupDir, "1panel-agent"), "/usr/local/bin/1panel-agent"); err != nil {
|
||||
global.LOG.Errorf("handle recover 1panel service file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
if err := fileOP.CopyDir(path.Join(backupDir, "db"), path.Join(global.CONF.System.BaseDir, "1panel")); err != nil {
|
||||
global.LOG.Errorf("handle recover 1panel db file failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadRestorePath(upgradeDir string) string {
|
||||
if _, err := os.Stat(upgradeDir); err != nil && os.IsNotExist(err) {
|
||||
return ""
|
||||
}
|
||||
files, err := os.ReadDir(upgradeDir)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var folders []string
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
folders = append(folders, file.Name())
|
||||
}
|
||||
}
|
||||
if len(folders) == 0 {
|
||||
return ""
|
||||
}
|
||||
sort.Slice(folders, func(i, j int) bool {
|
||||
return folders[i] > folders[j]
|
||||
})
|
||||
return folders[0]
|
||||
}
|
@ -26,6 +26,17 @@ func Init() {
|
||||
if err != nil {
|
||||
global.LOG.Fatalf("load current node before start failed, err: %v", err)
|
||||
}
|
||||
baseDir, err := settingRepo.Get(settingRepo.WithByKey("BaseDir"))
|
||||
if err != nil {
|
||||
global.LOG.Fatalf("load base dir before start failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.BaseDir = baseDir.Value
|
||||
version, err := settingRepo.Get(settingRepo.WithByKey("Version"))
|
||||
if err != nil {
|
||||
global.LOG.Fatalf("load base dir before start failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.Version = version.Value
|
||||
|
||||
global.IsMaster = node.Value == "127.0.0.1" || len(node.Value) == 0
|
||||
if global.IsMaster {
|
||||
db.InitCoreDB()
|
||||
|
@ -78,6 +78,12 @@ var InitSetting = &gormigrate.Migration{
|
||||
return err
|
||||
}
|
||||
global.IsMaster = isMaster
|
||||
if err := tx.Create(&model.Setting{Key: "BaseDir", Value: global.CONF.System.BaseDir}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "CurrentNode", Value: currentNode}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "CurrentNode", Value: currentNode}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -38,9 +38,6 @@ func Init() {
|
||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||
}
|
||||
} else {
|
||||
baseDir = loadParams("BASE_DIR")
|
||||
version = loadParams("ORIGINAL_VERSION")
|
||||
|
||||
reader := bytes.NewReader(conf.AppYaml)
|
||||
if err := v.ReadConfig(reader); err != nil {
|
||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||
|
@ -21,5 +21,6 @@ func commonGroups() []CommonRouter {
|
||||
&RuntimeRouter{},
|
||||
&ProcessRouter{},
|
||||
&WebsiteCARouter{},
|
||||
&UpgradeRouter{},
|
||||
}
|
||||
}
|
||||
|
17
agent/router/ro_upgrade.go
Normal file
17
agent/router/ro_upgrade.go
Normal file
@ -0,0 +1,17 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
v2 "github.com/1Panel-dev/1Panel/agent/app/api/v2"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UpgradeRouter struct{}
|
||||
|
||||
func (s *UpgradeRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
upgradeRouter := Router.Group("upgrades")
|
||||
baseApi := v2.ApiGroupApp.BaseApi
|
||||
{
|
||||
upgradeRouter.POST("/upgrade", baseApi.Upgrade)
|
||||
upgradeRouter.POST("/rollback", baseApi.Rollback)
|
||||
}
|
||||
}
|
@ -6,11 +6,9 @@ import (
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
cmdUtils "github.com/1Panel-dev/1Panel/core/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/files"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -45,31 +43,20 @@ var restoreCmd = &cobra.Command{
|
||||
tmpPath = path.Join(upgradeDir, tmpPath, "original")
|
||||
fmt.Printf("(0/4) 开始从 %s 目录回滚 1Panel 服务及数据... \n", tmpPath)
|
||||
|
||||
if err := files.CopyFile(path.Join(tmpPath, "1panel"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpPath, "1panel*"), "/usr/local/bin"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(1/4) 1panel 二进制回滚成功")
|
||||
if err := files.CopyFile(path.Join(tmpPath, "1pctl"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpPath, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(2/4) 1panel 脚本回滚成功")
|
||||
if err := files.CopyFile(path.Join(tmpPath, "1panel.service"), "/etc/systemd/system", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpPath, "1panel*.service"), "/etc/systemd/system"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(3/4) 1panel 服务回滚成功")
|
||||
checkPointOfWal()
|
||||
if _, err := os.Stat(path.Join(tmpPath, "core.db")); err == nil {
|
||||
if err := files.CopyFile(path.Join(tmpPath, "core.db"), path.Join(baseDir, "core/db"), false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path.Join(tmpPath, "agent.db")); err == nil {
|
||||
if err := files.CopyFile(path.Join(tmpPath, "agent.db"), path.Join(baseDir, "1panel/db"), false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path.Join(tmpPath, "db.tar.gz")); err == nil {
|
||||
if err := handleUnTar(path.Join(tmpPath, "db.tar.gz"), path.Join(baseDir, "1panel")); err != nil {
|
||||
if err := files.CopyItem(true, true, path.Join(tmpPath, "db"), path.Join(baseDir, "1panel")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -80,14 +67,6 @@ var restoreCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func checkPointOfWal() {
|
||||
db, err := loadDBConn()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = db.Exec("PRAGMA wal_checkpoint(TRUNCATE);").Error
|
||||
}
|
||||
|
||||
func loadRestorePath(upgradeDir string) (string, error) {
|
||||
if _, err := os.Stat(upgradeDir); err != nil && os.IsNotExist(err) {
|
||||
return "暂无可回滚文件", nil
|
||||
@ -110,18 +89,3 @@ func loadRestorePath(upgradeDir string) (string, error) {
|
||||
})
|
||||
return folders[0], nil
|
||||
}
|
||||
|
||||
func handleUnTar(sourceFile, targetDir string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
commands := fmt.Sprintf("tar zxvfC %s %s", sourceFile, targetDir)
|
||||
stdout, err := cmdUtils.ExecWithTimeOut(commands, 20*time.Second)
|
||||
if err != nil {
|
||||
return errors.New(stdout)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -83,8 +83,10 @@ func (u *UpgradeService) LoadNotes(req dto.Upgrade) (string, error) {
|
||||
func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
global.LOG.Info("start to upgrade now...")
|
||||
timeStr := time.Now().Format(constant.DateTimeSlimLayout)
|
||||
rootDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/tmp/upgrade/upgrade_%s/downloads", timeStr))
|
||||
originalDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/tmp/upgrade/upgrade_%s/original", timeStr))
|
||||
baseDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/tmp/upgrade/%s", req.Version))
|
||||
rootDir := path.Join(baseDir, fmt.Sprintf("upgrade_%s/downloads", timeStr))
|
||||
_ = os.RemoveAll(baseDir)
|
||||
originalDir := path.Join(baseDir, fmt.Sprintf("upgrade_%s/original", timeStr))
|
||||
if err := os.MkdirAll(rootDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -127,13 +129,13 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
}
|
||||
global.LOG.Info("backup original data successful, now start to upgrade!")
|
||||
|
||||
if err := files.CopyFile(path.Join(tmpDir, "1panel"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpDir, "1panel*"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1panel failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 1)
|
||||
return
|
||||
}
|
||||
|
||||
if err := files.CopyFile(path.Join(tmpDir, "1pctl"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpDir, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1pctl failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 2)
|
||||
return
|
||||
@ -144,7 +146,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
return
|
||||
}
|
||||
|
||||
if err := files.CopyFile(path.Join(tmpDir, "1panel.service"), "/etc/systemd/system", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(tmpDir, "1panel*.service"), "/etc/systemd/system"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 3)
|
||||
return
|
||||
@ -154,24 +156,22 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
go writeLogs(req.Version)
|
||||
_ = settingRepo.Update("SystemVersion", req.Version)
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
checkPointOfWal()
|
||||
_, _ = cmd.ExecWithTimeOut("systemctl daemon-reload && systemctl restart 1panel.service", 1*time.Minute)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UpgradeService) handleBackup(originalDir string) error {
|
||||
if err := files.CopyFile("/usr/local/bin/1panel", originalDir, false); err != nil {
|
||||
if err := files.CopyItem(false, true, "/usr/local/bin/1panel*", originalDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := files.CopyFile("/usr/local/bin/1pctl", originalDir, false); err != nil {
|
||||
if err := files.CopyItem(false, true, "/usr/local/bin/1pctl", originalDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := files.CopyFile("/etc/systemd/system/1panel.service", originalDir, false); err != nil {
|
||||
if err := files.CopyItem(false, true, "/etc/systemd/system/1panel*.service", originalDir); err != nil {
|
||||
return err
|
||||
}
|
||||
checkPointOfWal()
|
||||
if err := files.HandleTar(path.Join(global.CONF.System.BaseDir, "1panel/db"), originalDir, "db.tar.gz", "db/1Panel.db-*", ""); err != nil {
|
||||
if err := files.CopyItem(true, true, path.Join(global.CONF.System.BaseDir, "1panel/db"), originalDir); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -180,31 +180,25 @@ func (u *UpgradeService) handleBackup(originalDir string) error {
|
||||
func (u *UpgradeService) handleRollback(originalDir string, errStep int) {
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
|
||||
checkPointOfWal()
|
||||
dbPath := path.Join(global.CONF.System.BaseDir, "1panel/db")
|
||||
if _, err := os.Stat(path.Join(originalDir, "1Panel.db")); err == nil {
|
||||
if err := files.CopyFile(path.Join(originalDir, "1Panel.db"), dbPath, false); err != nil {
|
||||
if _, err := os.Stat(path.Join(originalDir, "db")); err == nil {
|
||||
if err := files.CopyItem(true, true, path.Join(originalDir, "db"), dbPath); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path.Join(originalDir, "db.tar.gz")); err == nil {
|
||||
if err := files.HandleUnTar(path.Join(originalDir, "db.tar.gz"), dbPath, ""); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
if err := files.CopyFile(path.Join(originalDir, "1panel"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(originalDir, "1panel*"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("rollback 1pctl failed, err: %v", err)
|
||||
}
|
||||
if errStep == 1 {
|
||||
return
|
||||
}
|
||||
if err := files.CopyFile(path.Join(originalDir, "1pctl"), "/usr/local/bin", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(originalDir, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
if errStep == 2 {
|
||||
return
|
||||
}
|
||||
if err := files.CopyFile(path.Join(originalDir, "1panel.service"), "/etc/systemd/system", false); err != nil {
|
||||
if err := files.CopyItem(false, true, path.Join(originalDir, "1panel*.service"), "/etc/systemd/system"); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
@ -345,9 +339,3 @@ func loadArch() (string, error) {
|
||||
}
|
||||
return "", fmt.Errorf("unsupported such arch: %s", std)
|
||||
}
|
||||
|
||||
func checkPointOfWal() {
|
||||
if err := global.DB.Exec("PRAGMA wal_checkpoint(TRUNCATE);").Error; err != nil {
|
||||
global.LOG.Errorf("handle check point failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,5 @@ const (
|
||||
StatusStarting = "starting"
|
||||
StatusHealthy = "healthy"
|
||||
StatusUnhealthy = "unhealthy"
|
||||
StatusUpgrading = "upgrading"
|
||||
)
|
||||
|
@ -40,6 +40,11 @@ func Init() {
|
||||
global.LOG.Errorf("load service ssl from setting failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.SSL = sslSetting.Value
|
||||
versionSetting, err := settingRepo.Get(commonRepo.WithByKey("SystemVersion"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load version from setting failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.Version = versionSetting.Value
|
||||
|
||||
if _, err := settingRepo.Get(commonRepo.WithByKey("SystemStatus")); err != nil {
|
||||
_ = settingRepo.Create("SystemStatus", "Free")
|
||||
|
@ -47,6 +47,30 @@ func CopyFile(src, dst string, withName bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CopyItem(isDir, withName bool, src, dst string) error {
|
||||
if path.Base(src) != path.Base(dst) && !withName {
|
||||
dst = path.Join(dst, path.Base(src))
|
||||
}
|
||||
srcInfo, err := os.Stat(path.Dir(src))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(path.Dir(dst)); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
_ = os.MkdirAll(path.Dir(dst), srcInfo.Mode())
|
||||
}
|
||||
}
|
||||
cmdStr := fmt.Sprintf(`cp -rf %s %s`, src, dst+"/")
|
||||
if !isDir {
|
||||
cmdStr = fmt.Sprintf(`cp -f %s %s`, src, dst+"/")
|
||||
}
|
||||
stdout, err := cmd.Exec(cmdStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("handle %s failed, stdout: %s, err: %v", cmdStr, stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
|
@ -71,6 +71,17 @@ func (c *SSHClient) Run(shell string) (string, error) {
|
||||
return string(buf), err
|
||||
}
|
||||
|
||||
func (c *SSHClient) Runf(shell string, args ...interface{}) (string, error) {
|
||||
session, err := c.Client.NewSession()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer session.Close()
|
||||
buf, err := session.CombinedOutput(fmt.Sprintf(shell, args...))
|
||||
|
||||
return string(buf), err
|
||||
}
|
||||
|
||||
func (c *SSHClient) Close() {
|
||||
_ = c.Client.Close()
|
||||
}
|
||||
|
@ -130,11 +130,11 @@ export const loadSnapshotSize = (param: SearchWithPage) => {
|
||||
|
||||
// upgrade
|
||||
export const loadUpgradeInfo = () => {
|
||||
return http.get<Setting.UpgradeInfo>(`/settings/upgrade`);
|
||||
return http.get<Setting.UpgradeInfo>(`/core/settings/upgrade`);
|
||||
};
|
||||
export const loadReleaseNotes = (version: string) => {
|
||||
return http.post<string>(`/settings/upgrade/notes`, { version: version });
|
||||
return http.post<string>(`/core/settings/upgrade/notes`, { version: version });
|
||||
};
|
||||
export const upgrade = (version: string) => {
|
||||
return http.post(`/settings/upgrade`, { version: version });
|
||||
return http.post(`/core/settings/upgrade`, { version: version });
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user