mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-13 17:24:44 +08:00
feat(system-upgrade): Added support for multi-host upgrade and rollback (#7178)
* feat(system-upgrade): Added support for multi-host upgrade * feat: Add supports of task display for node upgrade
This commit is contained in:
parent
df3f105cf0
commit
45362a9819
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
|
||||
|
6
Makefile
6
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:
|
||||
@ -61,4 +61,4 @@ build_xpack_all: build_frontend build_core_xpack_on_linux build_agent_xpack_on_l
|
||||
|
||||
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin
|
||||
|
||||
build_xpack_on_local: clean_assets build_frontend build_agent_xpack_on_darwin build_agent_xpack_on_darwin upx_bin
|
||||
build_xpack_on_local: clean_assets build_frontend build_core_xpack_on_darwin build_agent_xpack_on_darwin upx_bin
|
||||
|
@ -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")
|
||||
},
|
||||
|
@ -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("SystemVersion"))
|
||||
if err != nil {
|
||||
global.LOG.Fatalf("load system version 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()
|
||||
|
@ -15,7 +15,6 @@ func Init() {
|
||||
migrations.InitImageRepo,
|
||||
migrations.InitDefaultCA,
|
||||
migrations.InitPHPExtensions,
|
||||
migrations.AddTask,
|
||||
migrations.UpdateWebsite,
|
||||
migrations.UpdateWebsiteDomain,
|
||||
migrations.UpdateApp,
|
||||
@ -23,6 +22,7 @@ func Init() {
|
||||
migrations.UpdateAppInstall,
|
||||
migrations.UpdateSnapshot,
|
||||
migrations.UpdateCronjob,
|
||||
migrations.InitBaseDir,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -53,7 +53,6 @@ var AddTable = &gormigrate.Migration{
|
||||
&model.WebsiteDnsAccount{},
|
||||
&model.WebsiteDomain{},
|
||||
&model.WebsiteSSL{},
|
||||
&model.Task{},
|
||||
)
|
||||
},
|
||||
}
|
||||
@ -78,6 +77,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
|
||||
}
|
||||
@ -211,14 +216,6 @@ var InitPHPExtensions = &gormigrate.Migration{
|
||||
},
|
||||
}
|
||||
|
||||
var AddTask = &gormigrate.Migration{
|
||||
ID: "20240802-add-task",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&model.Task{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateWebsite = &gormigrate.Migration{
|
||||
ID: "20240812-update-website",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
@ -273,3 +270,13 @@ var UpdateCronjob = &gormigrate.Migration{
|
||||
return tx.AutoMigrate(&model.Cronjob{}, &model.JobRecords{})
|
||||
},
|
||||
}
|
||||
|
||||
var InitBaseDir = &gormigrate.Migration{
|
||||
ID: "20241122-init-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "BaseDir", Value: global.CONF.System.BaseDir}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
}
|
||||
|
13
core/app/dto/task.go
Normal file
13
core/app/dto/task.go
Normal file
@ -0,0 +1,13 @@
|
||||
package dto
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/core/app/model"
|
||||
|
||||
type SearchTaskLogReq struct {
|
||||
Status string `json:"status"`
|
||||
Type string `json:"type"`
|
||||
PageInfo
|
||||
}
|
||||
|
||||
type TaskDTO struct {
|
||||
model.Task
|
||||
}
|
18
core/app/model/task.go
Normal file
18
core/app/model/task.go
Normal file
@ -0,0 +1,18 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Task struct {
|
||||
ID string `gorm:"primarykey;" json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Operate string `json:"operate"`
|
||||
LogFile string `json:"logFile"`
|
||||
Status string `json:"status"`
|
||||
ErrorMsg string `json:"errorMsg"`
|
||||
OperationLogID uint `json:"operationLogID"`
|
||||
ResourceID uint `json:"resourceID"`
|
||||
CurrentStep string `json:"currentStep"`
|
||||
EndAt time.Time `json:"endAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
9
core/app/model/upgrade_log.go
Normal file
9
core/app/model/upgrade_log.go
Normal file
@ -0,0 +1,9 @@
|
||||
package model
|
||||
|
||||
type UpgradeLog struct {
|
||||
BaseModel
|
||||
NodeID uint `json:"nodeID"`
|
||||
OldVersion string `json:"oldVersion"`
|
||||
NewVersion string `json:"newVersion"`
|
||||
BackupFile string `json:"backupFile"`
|
||||
}
|
@ -17,6 +17,7 @@ type ICommonRepo interface {
|
||||
WithByType(ty string) DBOption
|
||||
WithByKey(key string) DBOption
|
||||
WithOrderBy(orderStr string) DBOption
|
||||
WithByStatus(status string) DBOption
|
||||
|
||||
WithOrderRuleBy(orderBy, order string) DBOption
|
||||
}
|
||||
@ -66,6 +67,11 @@ func (c *CommonRepo) WithByKey(key string) DBOption {
|
||||
return g.Where("key = ?", key)
|
||||
}
|
||||
}
|
||||
func (c *CommonRepo) WithByStatus(status string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("status = ?", status)
|
||||
}
|
||||
}
|
||||
func (c *CommonRepo) WithOrderBy(orderStr string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Order(orderStr)
|
||||
|
90
core/app/repo/task.go
Normal file
90
core/app/repo/task.go
Normal file
@ -0,0 +1,90 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type TaskRepo struct {
|
||||
}
|
||||
|
||||
type ITaskRepo interface {
|
||||
Save(ctx context.Context, task *model.Task) error
|
||||
GetFirst(opts ...DBOption) (model.Task, error)
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.Task, error)
|
||||
Update(ctx context.Context, task *model.Task) error
|
||||
|
||||
WithByID(id string) DBOption
|
||||
WithResourceID(id uint) DBOption
|
||||
WithOperate(taskOperate string) DBOption
|
||||
}
|
||||
|
||||
func NewITaskRepo() ITaskRepo {
|
||||
return &TaskRepo{}
|
||||
}
|
||||
|
||||
func getTaskDb(opts ...DBOption) *gorm.DB {
|
||||
db := global.TaskDB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func getTaskTx(ctx context.Context, opts ...DBOption) *gorm.DB {
|
||||
tx, ok := ctx.Value("db").(*gorm.DB)
|
||||
if ok {
|
||||
for _, opt := range opts {
|
||||
tx = opt(tx)
|
||||
}
|
||||
return tx
|
||||
}
|
||||
return getTaskDb(opts...)
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithByID(id string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id = ?", id)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithOperate(taskOperate string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("operate = ?", taskOperate)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithResourceID(id uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("resource_id = ?", id)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) Save(ctx context.Context, task *model.Task) error {
|
||||
return getTaskTx(ctx).Save(&task).Error
|
||||
}
|
||||
|
||||
func (t TaskRepo) GetFirst(opts ...DBOption) (model.Task, error) {
|
||||
var task model.Task
|
||||
db := getTaskDb(opts...).Model(&model.Task{})
|
||||
if err := db.First(&task).Error; err != nil {
|
||||
return task, err
|
||||
}
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (t TaskRepo) Page(page, size int, opts ...DBOption) (int64, []model.Task, error) {
|
||||
var tasks []model.Task
|
||||
db := getTaskDb(opts...).Model(&model.Task{})
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&tasks).Error
|
||||
return count, tasks, err
|
||||
}
|
||||
|
||||
func (t TaskRepo) Update(ctx context.Context, task *model.Task) error {
|
||||
return getTaskTx(ctx).Save(&task).Error
|
||||
}
|
93
core/app/repo/upgrade_log.go
Normal file
93
core/app/repo/upgrade_log.go
Normal file
@ -0,0 +1,93 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UpgradeLogRepo struct{}
|
||||
|
||||
type IUpgradeLogRepo interface {
|
||||
Get(opts ...DBOption) (model.UpgradeLog, error)
|
||||
List(opts ...DBOption) ([]model.UpgradeLog, error)
|
||||
Create(log *model.UpgradeLog) error
|
||||
Page(limit, offset int, opts ...DBOption) (int64, []model.UpgradeLog, error)
|
||||
Delete(opts ...DBOption) error
|
||||
|
||||
WithByNodeID(nodeID uint) DBOption
|
||||
WithByIDs(ids []uint) DBOption
|
||||
WithByID(id uint) DBOption
|
||||
}
|
||||
|
||||
func NewIUpgradeLogRepo() IUpgradeLogRepo {
|
||||
return &UpgradeLogRepo{}
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Get(opts ...DBOption) (model.UpgradeLog, error) {
|
||||
var log model.UpgradeLog
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.First(&log).Error
|
||||
return log, err
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) List(opts ...DBOption) ([]model.UpgradeLog, error) {
|
||||
var logs []model.UpgradeLog
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&logs).Error
|
||||
return logs, err
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Clean() error {
|
||||
return global.DB.Exec("delete from upgrade_logs;").Error
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Create(log *model.UpgradeLog) error {
|
||||
return global.DB.Create(log).Error
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Save(log *model.UpgradeLog) error {
|
||||
return global.DB.Save(log).Error
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Delete(opts ...DBOption) error {
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db.Delete(&model.UpgradeLog{}).Error
|
||||
}
|
||||
|
||||
func (u *UpgradeLogRepo) Page(page, size int, opts ...DBOption) (int64, []model.UpgradeLog, error) {
|
||||
var ops []model.UpgradeLog
|
||||
db := global.DB.Model(&model.UpgradeLog{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&ops).Error
|
||||
return count, ops, err
|
||||
}
|
||||
|
||||
func (c *UpgradeLogRepo) WithByNodeID(nodeID uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("node_id = ?", nodeID)
|
||||
}
|
||||
}
|
||||
func (c *UpgradeLogRepo) WithByID(id uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id = ?", id)
|
||||
}
|
||||
}
|
||||
func (c *UpgradeLogRepo) WithByIDs(ids []uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id in (?)", ids)
|
||||
}
|
||||
}
|
@ -11,4 +11,6 @@ var (
|
||||
logRepo = repo.NewILogRepo()
|
||||
groupRepo = repo.NewIGroupRepo()
|
||||
launcherRepo = repo.NewILauncherRepo()
|
||||
|
||||
taskRepo = repo.NewITaskRepo()
|
||||
)
|
||||
|
42
core/app/service/task.go
Normal file
42
core/app/service/task.go
Normal file
@ -0,0 +1,42 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
)
|
||||
|
||||
type TaskLogService struct{}
|
||||
|
||||
type ITaskLogService interface {
|
||||
Page(req dto.SearchTaskLogReq) (int64, []dto.TaskDTO, error)
|
||||
}
|
||||
|
||||
func NewITaskService() ITaskLogService {
|
||||
return &TaskLogService{}
|
||||
}
|
||||
|
||||
func (u *TaskLogService) Page(req dto.SearchTaskLogReq) (int64, []dto.TaskDTO, error) {
|
||||
opts := []repo.DBOption{
|
||||
commonRepo.WithOrderBy("created_at desc"),
|
||||
}
|
||||
if req.Status != "" {
|
||||
opts = append(opts, commonRepo.WithByStatus(req.Status))
|
||||
}
|
||||
if req.Type != "" {
|
||||
opts = append(opts, commonRepo.WithByType(req.Type))
|
||||
}
|
||||
|
||||
total, tasks, err := taskRepo.Page(
|
||||
req.Page,
|
||||
req.PageSize,
|
||||
opts...,
|
||||
)
|
||||
var items []dto.TaskDTO
|
||||
for _, t := range tasks {
|
||||
item := dto.TaskDTO{
|
||||
Task: t,
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return total, items, err
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
253
core/app/task/task.go
Normal file
253
core/app/task/task.go
Normal file
@ -0,0 +1,253 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/i18n"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ActionFunc func(*Task) error
|
||||
type RollbackFunc func(*Task)
|
||||
|
||||
type Task struct {
|
||||
Name string
|
||||
TaskID string
|
||||
Logger *log.Logger
|
||||
SubTasks []*SubTask
|
||||
Rollbacks []RollbackFunc
|
||||
logFile *os.File
|
||||
taskRepo repo.ITaskRepo
|
||||
Task *model.Task
|
||||
ParentID string
|
||||
}
|
||||
|
||||
type SubTask struct {
|
||||
RootTask *Task
|
||||
Name string
|
||||
StepAlias string
|
||||
Retry int
|
||||
Timeout time.Duration
|
||||
Action ActionFunc
|
||||
Rollback RollbackFunc
|
||||
Error error
|
||||
IgnoreErr bool
|
||||
}
|
||||
|
||||
const (
|
||||
TaskUpgrade = "TaskUpgrade"
|
||||
TaskAddNode = "TaskAddNode"
|
||||
)
|
||||
|
||||
const (
|
||||
TaskScopeSystem = "System"
|
||||
)
|
||||
|
||||
const (
|
||||
TaskSuccess = "Success"
|
||||
TaskFailed = "Failed"
|
||||
)
|
||||
|
||||
func GetTaskName(resourceName, operate, scope string) string {
|
||||
return fmt.Sprintf("%s%s [%s]", i18n.GetMsgByKey(operate), i18n.GetMsgByKey(scope), resourceName)
|
||||
}
|
||||
|
||||
func NewTaskWithOps(resourceName, operate, scope, taskID string, resourceID uint) (*Task, error) {
|
||||
return NewTask(GetTaskName(resourceName, operate, scope), operate, scope, taskID, resourceID)
|
||||
}
|
||||
|
||||
func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, error) {
|
||||
if taskID == "" {
|
||||
taskID = uuid.New().String()
|
||||
}
|
||||
logItem := path.Join(global.CONF.System.BaseDir, "1panel/log")
|
||||
logDir := path.Join(logItem, taskScope)
|
||||
if _, err := os.Stat(logDir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(logDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||||
}
|
||||
}
|
||||
logPath := path.Join(logItem, taskScope, taskID+".log")
|
||||
file, err := os.OpenFile(logPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open log file: %w", err)
|
||||
}
|
||||
logger := log.New(file, "", log.LstdFlags)
|
||||
taskModel := &model.Task{
|
||||
ID: taskID,
|
||||
Name: name,
|
||||
Type: taskScope,
|
||||
LogFile: logPath,
|
||||
Status: constant.StatusRunning,
|
||||
ResourceID: resourceID,
|
||||
Operate: operate,
|
||||
}
|
||||
taskRepo := repo.NewITaskRepo()
|
||||
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel}
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (t *Task) AddSubTask(name string, action ActionFunc, rollback RollbackFunc) {
|
||||
subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 10 * time.Minute, Action: action, Rollback: rollback}
|
||||
t.SubTasks = append(t.SubTasks, subTask)
|
||||
}
|
||||
|
||||
func (t *Task) AddSubTaskWithAlias(key string, action ActionFunc, rollback RollbackFunc) {
|
||||
subTask := &SubTask{RootTask: t, Name: i18n.GetMsgByKey(key), StepAlias: key, Retry: 0, Timeout: 10 * time.Minute, Action: action, Rollback: rollback}
|
||||
t.SubTasks = append(t.SubTasks, subTask)
|
||||
}
|
||||
|
||||
func (t *Task) AddSubTaskWithOps(name string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) {
|
||||
subTask := &SubTask{RootTask: t, Name: name, Retry: retry, Timeout: timeout, Action: action, Rollback: rollback}
|
||||
t.SubTasks = append(t.SubTasks, subTask)
|
||||
}
|
||||
|
||||
func (t *Task) AddSubTaskWithIgnoreErr(name string, action ActionFunc) {
|
||||
subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 10 * time.Minute, Action: action, Rollback: nil, IgnoreErr: true}
|
||||
t.SubTasks = append(t.SubTasks, subTask)
|
||||
}
|
||||
|
||||
func (s *SubTask) Execute() error {
|
||||
subTaskName := s.Name
|
||||
if s.Name == "" {
|
||||
subTaskName = i18n.GetMsgByKey("SubTask")
|
||||
}
|
||||
var err error
|
||||
for i := 0; i < s.Retry+1; i++ {
|
||||
if i > 0 {
|
||||
s.RootTask.Log(i18n.GetWithName("TaskRetry", strconv.Itoa(i)))
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), s.Timeout)
|
||||
defer cancel()
|
||||
|
||||
done := make(chan error)
|
||||
go func() {
|
||||
done <- s.Action(s.RootTask)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
s.RootTask.Log(i18n.GetWithName("TaskTimeout", subTaskName))
|
||||
case err = <-done:
|
||||
if err != nil {
|
||||
s.RootTask.Log(i18n.GetWithNameAndErr("SubTaskFailed", subTaskName, err))
|
||||
} else {
|
||||
s.RootTask.Log(i18n.GetWithName("SubTaskSuccess", subTaskName))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if i == s.Retry {
|
||||
if s.Rollback != nil {
|
||||
s.Rollback(s.RootTask)
|
||||
}
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *Task) updateTask(task *model.Task) {
|
||||
_ = t.taskRepo.Update(context.Background(), task)
|
||||
}
|
||||
|
||||
func (t *Task) Execute() error {
|
||||
if err := t.taskRepo.Save(context.Background(), t.Task); err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
t.Log(i18n.GetWithName("TaskStart", t.Name))
|
||||
for _, subTask := range t.SubTasks {
|
||||
t.Task.CurrentStep = subTask.StepAlias
|
||||
t.updateTask(t.Task)
|
||||
if err = subTask.Execute(); err == nil {
|
||||
if subTask.Rollback != nil {
|
||||
t.Rollbacks = append(t.Rollbacks, subTask.Rollback)
|
||||
}
|
||||
} else {
|
||||
if subTask.IgnoreErr {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
t.Task.ErrorMsg = err.Error()
|
||||
t.Task.Status = constant.StatusFailed
|
||||
for _, rollback := range t.Rollbacks {
|
||||
rollback(t)
|
||||
}
|
||||
t.updateTask(t.Task)
|
||||
break
|
||||
}
|
||||
}
|
||||
if t.Task.Status == constant.StatusRunning {
|
||||
t.Task.Status = constant.StatusSuccess
|
||||
t.Log(i18n.GetWithName("TaskSuccess", t.Name))
|
||||
} else {
|
||||
t.Log(i18n.GetWithName("TaskFailed", t.Name))
|
||||
}
|
||||
t.Log("[TASK-END]")
|
||||
t.Task.EndAt = time.Now()
|
||||
t.updateTask(t.Task)
|
||||
_ = t.logFile.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *Task) DeleteLogFile() {
|
||||
_ = os.Remove(t.Task.LogFile)
|
||||
}
|
||||
|
||||
func (t *Task) LogWithStatus(msg string, err error) {
|
||||
if err != nil {
|
||||
t.Logger.Printf(i18n.GetWithNameAndErr("FailedStatus", msg, err))
|
||||
} else {
|
||||
t.Logger.Printf(i18n.GetWithName("SuccessStatus", msg))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Task) Log(msg string) {
|
||||
t.Logger.Printf(msg)
|
||||
}
|
||||
|
||||
func (t *Task) Logf(format string, v ...any) {
|
||||
t.Logger.Printf(format, v...)
|
||||
}
|
||||
|
||||
func (t *Task) LogFailed(msg string) {
|
||||
t.Logger.Printf(msg + i18n.GetMsgByKey("Failed"))
|
||||
}
|
||||
|
||||
func (t *Task) LogFailedWithErr(msg string, err error) {
|
||||
t.Logger.Printf(fmt.Sprintf("%s %s : %s", msg, i18n.GetMsgByKey("Failed"), err.Error()))
|
||||
}
|
||||
|
||||
func (t *Task) LogSuccess(msg string) {
|
||||
t.Logger.Printf(msg + i18n.GetMsgByKey("Success"))
|
||||
}
|
||||
func (t *Task) LogSuccessF(format string, v ...any) {
|
||||
t.Logger.Printf(fmt.Sprintf(format, v...) + i18n.GetMsgByKey("Success"))
|
||||
}
|
||||
|
||||
func (t *Task) LogStart(msg string) {
|
||||
t.Logger.Printf(fmt.Sprintf("%s%s", i18n.GetMsgByKey("Start"), msg))
|
||||
}
|
||||
|
||||
func (t *Task) LogWithOps(operate, msg string) {
|
||||
t.Logger.Printf("%s%s", i18n.GetMsgByKey(operate), msg)
|
||||
}
|
||||
|
||||
func (t *Task) LogSuccessWithOps(operate, msg string) {
|
||||
t.Logger.Printf("%s%s%s", i18n.GetMsgByKey(operate), msg, i18n.GetMsgByKey("Success"))
|
||||
}
|
||||
|
||||
func (t *Task) LogFailedWithOps(operate, msg string, err error) {
|
||||
t.Logger.Printf("%s%s%s : %s ", i18n.GetMsgByKey(operate), msg, i18n.GetMsgByKey("Failed"), err.Error())
|
||||
}
|
@ -12,4 +12,6 @@ const (
|
||||
StatusStarting = "starting"
|
||||
StatusHealthy = "healthy"
|
||||
StatusUnhealthy = "unhealthy"
|
||||
StatusUpgrading = "upgrading"
|
||||
StatusRunning = "running"
|
||||
)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
|
||||
var (
|
||||
DB *gorm.DB
|
||||
TaskDB *gorm.DB
|
||||
LOG *logrus.Logger
|
||||
CONF configs.ServerConfig
|
||||
VALID *validator.Validate
|
||||
|
@ -32,25 +32,20 @@ func GetMsgWithMap(key string, maps map[string]interface{}) string {
|
||||
}
|
||||
}
|
||||
|
||||
func GetMsgWithName(key string, name string, err error) string {
|
||||
func GetMsgWithDetail(key string, detail string) string {
|
||||
var (
|
||||
content string
|
||||
dataMap = make(map[string]interface{})
|
||||
)
|
||||
dataMap["name"] = name
|
||||
if err != nil {
|
||||
dataMap["err"] = err.Error()
|
||||
}
|
||||
dataMap["detail"] = detail
|
||||
content, _ = global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: key,
|
||||
TemplateData: dataMap,
|
||||
})
|
||||
content = strings.ReplaceAll(content, "<no value>", "")
|
||||
if content == "" {
|
||||
return key
|
||||
} else {
|
||||
if content != "" {
|
||||
return content
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func GetErrMsg(key string, maps map[string]interface{}) string {
|
||||
@ -75,6 +70,41 @@ func GetMsgByKey(key string) string {
|
||||
return content
|
||||
}
|
||||
|
||||
func Get(key string) string {
|
||||
content, _ := global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: key,
|
||||
})
|
||||
if content != "" {
|
||||
return content
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func GetWithName(key string, name string) string {
|
||||
var (
|
||||
dataMap = make(map[string]interface{})
|
||||
)
|
||||
dataMap["name"] = name
|
||||
content, _ := global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: key,
|
||||
TemplateData: dataMap,
|
||||
})
|
||||
return content
|
||||
}
|
||||
|
||||
func GetWithNameAndErr(key string, name string, err error) string {
|
||||
var (
|
||||
dataMap = make(map[string]interface{})
|
||||
)
|
||||
dataMap["name"] = name
|
||||
dataMap["err"] = err.Error()
|
||||
content, _ := global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: key,
|
||||
TemplateData: dataMap,
|
||||
})
|
||||
return content
|
||||
}
|
||||
|
||||
//go:embed lang/*
|
||||
var fs embed.FS
|
||||
var bundle *i18n.Bundle
|
||||
|
@ -29,3 +29,42 @@ ErrNoSuchHost: "Network connection failed"
|
||||
ErrBackupInUsed: "The backup account is currently in use in a scheduled task and cannot be deleted."
|
||||
ErrBackupCheck: "Backup account test connection failed {{.err}}"
|
||||
ErrBackupLocalDelete: "Deleting local server backup accounts is not currently supported."
|
||||
|
||||
#task
|
||||
TaskStart: "{{.name}} Task Start [START]"
|
||||
TaskEnd: "{{.name}} Task End [COMPLETED]"
|
||||
TaskFailed: "{{.name}} Task Failed"
|
||||
TaskTimeout: "{{.name}} Timeout"
|
||||
TaskSuccess: "{{.name}} Task Successful"
|
||||
TaskRetry: "Starting the {{.name}} retry"
|
||||
SubTaskSuccess: "{{ .name }} Successful"
|
||||
SubTaskFailed: "{{ .name }} Failed: {{ .err }}"
|
||||
TaskInstall: "Install"
|
||||
TaskUninstall: "Uninstall"
|
||||
TaskCreate: "Create"
|
||||
TaskDelete: "Delete"
|
||||
TaskUpgrade: "Upgrade"
|
||||
TaskUpdate: "Update"
|
||||
TaskRestart: "Restart"
|
||||
TaskRollback: "Rollback"
|
||||
SuccessStatus: "{{ .name }} Successful"
|
||||
FailedStatus: "{{ .name }} Failed {{.err}}"
|
||||
PullImage: "Pull Image"
|
||||
Start: "Start"
|
||||
Run: "Launch"
|
||||
Stop: "Stop"
|
||||
SubTask: "Subtask"
|
||||
|
||||
#upgrade node
|
||||
NodeUpgrade: "Upgrade Node {name}"
|
||||
NewSSHClient: "Initialize SSH Connection"
|
||||
BackupBeforeUpgrade: "Backup Data Before Upgrade"
|
||||
UploadUpgradeFile: "Distribute Upgrade Required Files"
|
||||
RestartAfterUpgrade: "Start Service After Upgrade"
|
||||
|
||||
#add node
|
||||
TaskAddNode: "Add Node"
|
||||
GenerateSSLInfo: "Generate Node SSL Information"
|
||||
MakeAgentPackage: "Generate Node Installation Package"
|
||||
SendAgent: "Distribute Node Installation Package"
|
||||
StartService: "Start Service"
|
@ -28,4 +28,43 @@ ErrNoSuchHost: "網路連接失敗"
|
||||
#backup
|
||||
ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除"
|
||||
ErrBackupCheck: "備份帳號測試連接失敗 {{.err}}"
|
||||
ErrBackupLocalDelete: "暫不支持刪除本地伺服器備份帳號"
|
||||
ErrBackupLocalDelete: "暫不支持刪除本地伺服器備份帳號"
|
||||
|
||||
#task
|
||||
TaskStart: "{{.name}} 任務開始 [START]"
|
||||
TaskEnd: "{{.name}} 任務結束 [COMPLETED]"
|
||||
TaskFailed: "{{.name}} 任務失敗"
|
||||
TaskTimeout: "{{.name}} 超時"
|
||||
TaskSuccess: "{{.name}} 任務成功"
|
||||
TaskRetry: "開始第 {{.name}} 次重試"
|
||||
SubTaskSuccess: "{{ .name }} 成功"
|
||||
SubTaskFailed: "{{ .name }} 失敗: {{ .err }}"
|
||||
TaskInstall: "安裝"
|
||||
TaskUninstall: "卸載"
|
||||
TaskCreate: "創建"
|
||||
TaskDelete: "刪除"
|
||||
TaskUpgrade: "升級"
|
||||
TaskUpdate: "更新"
|
||||
TaskRestart: "重啟"
|
||||
TaskRollback: "回滾"
|
||||
SuccessStatus: "{{ .name }} 成功"
|
||||
FailedStatus: "{{ .name }} 失敗 {{.err}}"
|
||||
PullImage: "拉取鏡像"
|
||||
Start: "開始"
|
||||
Run: "啟動"
|
||||
Stop: "停止"
|
||||
SubTask: "子任務"
|
||||
|
||||
#node upgrade
|
||||
NodeUpgrade: "升級節點 {name}"
|
||||
NewSSHClient: "初始化 SSH 連接"
|
||||
BackupBeforeUpgrade: "升級前備份數據"
|
||||
UploadUpgradeFile: "下發升級所需文件"
|
||||
RestartAfterUpgrade: "升級後啟動服務"
|
||||
|
||||
#node create
|
||||
TaskAddNode: "添加節點"
|
||||
GenerateSSLInfo: "生成節點 SSL 信息"
|
||||
MakeAgentPackage: "生成節點安裝包"
|
||||
SendAgent: "下發節點安裝包"
|
||||
StartService: "啟動服務"
|
@ -30,4 +30,44 @@ ErrNoSuchHost: "网络连接失败"
|
||||
#backup
|
||||
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
|
||||
ErrBackupCheck: "备份账号测试连接失败 {{ .err}}"
|
||||
ErrBackupLocalDelete: "暂不支持删除本地服务器备份账号"
|
||||
ErrBackupLocalDelete: "暂不支持删除本地服务器备份账号"
|
||||
|
||||
#task
|
||||
#task
|
||||
TaskStart: "{{.name}} 任务开始 [START]"
|
||||
TaskEnd: "{{.name}} 任务结束 [COMPLETED]"
|
||||
TaskFailed: "{{.name}} 任务失败"
|
||||
TaskTimeout: "{{.name}} 超时"
|
||||
TaskSuccess: "{{.name}} 任务成功"
|
||||
TaskRetry: "开始第 {{.name}} 次重试"
|
||||
SubTaskSuccess: "{{ .name }} 成功"
|
||||
SubTaskFailed: "{{ .name }} 失败: {{ .err }}"
|
||||
TaskInstall: "安装"
|
||||
TaskUninstall: "卸载"
|
||||
TaskCreate: "创建"
|
||||
TaskDelete: "删除"
|
||||
TaskUpgrade: "升级"
|
||||
TaskUpdate: "更新"
|
||||
TaskRestart: "重启"
|
||||
TaskRollback: "回滚"
|
||||
SuccessStatus: "{{ .name }} 成功"
|
||||
FailedStatus: "{{ .name }} 失败 {{.err}}"
|
||||
PullImage: "拉取镜像"
|
||||
Start: "开始"
|
||||
Run: "启动"
|
||||
Stop: "停止"
|
||||
SubTask: "子任务"
|
||||
|
||||
#upgrade node
|
||||
NodeUpgrade: "升级节点 {name}"
|
||||
NewSSHClient: "初始化 SSH 连接"
|
||||
BackupBeforeUpgrade: "升级前备份数据"
|
||||
UploadUpgradeFile: "下发升级所需文件"
|
||||
RestartAfterUpgrade: "升级后启动服务"
|
||||
|
||||
#add node
|
||||
TaskAddNode: "添加节点"
|
||||
GenerateSSLInfo: "生成节点 SSL 信息"
|
||||
MakeAgentPackage: "生成节点安装包"
|
||||
SendAgent: "下发节点安装包"
|
||||
StartService: "启动服务"
|
@ -14,6 +14,11 @@ import (
|
||||
)
|
||||
|
||||
func Init() {
|
||||
initDB()
|
||||
initTaskDB()
|
||||
}
|
||||
|
||||
func initDB() {
|
||||
dbPath := path.Join(global.CONF.System.BaseDir, "1panel/db")
|
||||
if _, err := os.Stat(dbPath); err != nil {
|
||||
if err := os.MkdirAll(dbPath, os.ModePerm); err != nil {
|
||||
@ -29,7 +34,50 @@ func Init() {
|
||||
_ = f.Close()
|
||||
}
|
||||
|
||||
newLogger := logger.New(
|
||||
db, err := NewDBWithPath(fullPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
global.DB = db
|
||||
global.LOG.Info("init db successfully")
|
||||
}
|
||||
|
||||
func initTaskDB() {
|
||||
fullPath := path.Join(global.CONF.System.BaseDir, "1panel/db/task.db")
|
||||
if _, err := os.Stat(fullPath); err != nil {
|
||||
f, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("init task db file failed, err: %v", err))
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
|
||||
db, err := NewDBWithPath(fullPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
global.TaskDB = db
|
||||
global.LOG.Info("init task db successfully")
|
||||
}
|
||||
|
||||
func NewDBWithPath(dbPath string) (*gorm.DB, error) {
|
||||
db, _ := gorm.Open(sqlite.Open(dbPath), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
Logger: getLogger(),
|
||||
})
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
return nil, dbError
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
return db, nil
|
||||
}
|
||||
func getLogger() logger.Interface {
|
||||
return logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second,
|
||||
@ -38,22 +86,4 @@ func Init() {
|
||||
Colorful: false,
|
||||
},
|
||||
)
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
Logger: newLogger,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
panic(dbError)
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
global.DB = db
|
||||
global.LOG.Info("init db successfully")
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -18,6 +18,7 @@ func Init() {
|
||||
migrations.InitAppLauncher,
|
||||
migrations.InitBackup,
|
||||
migrations.InitGoogle,
|
||||
migrations.AddTaskDB,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
var AddTable = &gormigrate.Migration{
|
||||
ID: "20240819-add-table",
|
||||
ID: "20241224-add-table",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&model.OperationLog{},
|
||||
@ -25,6 +25,7 @@ var AddTable = &gormigrate.Migration{
|
||||
&model.Group{},
|
||||
&model.Host{},
|
||||
&model.Command{},
|
||||
&model.UpgradeLog{},
|
||||
)
|
||||
},
|
||||
}
|
||||
@ -260,3 +261,12 @@ var InitGoogle = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddTaskDB = &gormigrate.Migration{
|
||||
ID: "20241125-add-task-table",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return global.TaskDB.AutoMigrate(
|
||||
&model.Task{},
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -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…
x
Reference in New Issue
Block a user