1Panel/backend/app/service/snapshot.go

151 lines
5.0 KiB
Go
Raw Normal View History

2023-01-06 18:53:25 +08:00
package service
import (
"context"
"fmt"
"os"
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
)
type SnapshotService struct{}
type ISnapshotService interface {
SearchWithPage(req dto.PageInfo) (int64, interface{}, error)
Create(req dto.SnapshotCreate) error
}
func NewISnapshotService() ISnapshotService {
return &SnapshotService{}
}
func (u *SnapshotService) SearchWithPage(req dto.PageInfo) (int64, interface{}, error) {
total, snapshots, err := snapshotRepo.Page(req.Page, req.PageSize)
var dtoSnap []dto.SnapshotInfo
for _, snapshot := range snapshots {
var item dto.SnapshotInfo
if err := copier.Copy(&item, &snapshot); err != nil {
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
dtoSnap = append(dtoSnap, item)
}
return total, dtoSnap, err
}
func (u *SnapshotService) Create(req dto.SnapshotCreate) error {
localDir, err := loadLocalDir()
if err != nil {
return err
}
backup, err := backupRepo.Get(commonRepo.WithByType(req.BackupType))
if err != nil {
return err
}
backupAccont, err := NewIBackupService().NewClient(&backup)
if err != nil {
return err
}
timeNow := time.Now().Format("20060102150405")
rootDir := fmt.Sprintf("/tmp/songliu/1panel_backup_%s", timeNow)
backupPanelDir := fmt.Sprintf("%s/1panel", rootDir)
_ = os.MkdirAll(backupPanelDir, os.ModePerm)
backupDockerDir := fmt.Sprintf("%s/docker", rootDir)
_ = os.MkdirAll(backupDockerDir, os.ModePerm)
defer func() {
_, _ = cmd.Exec("systemctl start docker")
_ = os.RemoveAll(rootDir)
}()
fileOp := files.NewFileOp()
if err := fileOp.Compress([]string{localDir}, backupPanelDir, "1panel_backup.tar.gz", files.TarGz); err != nil {
global.LOG.Errorf("snapshot backup 1panel backup datas %s failed, err: %v", localDir, err)
return err
}
client, err := docker.NewDockerClient()
if err != nil {
return err
}
ctx := context.Background()
info, err := client.Info(ctx)
if err != nil {
return err
}
dataDir := info.DockerRootDir
stdout, err := cmd.Exec("systemctl stop docker")
if err != nil {
return errors.New(stdout)
}
if _, err := os.Stat("/etc/systemd/system/1panel.service"); err == nil {
if err := fileOp.Compress([]string{dataDir}, backupDockerDir, "docker_data.tar.gz", files.TarGz); err != nil {
global.LOG.Errorf("snapshot backup docker data dir %s failed, err: %v", dataDir, err)
return err
}
}
if _, err := os.Stat(constant.DaemonJsonPath); err == nil {
if err := fileOp.CopyFile(constant.DaemonJsonPath, backupDockerDir); err != nil {
global.LOG.Errorf("snapshot backup daemon.json failed, err: %v", err)
return err
}
}
if _, err := os.Stat("/Users/slooop/go/bin/swag"); err == nil {
if err := fileOp.CopyFile("/Users/slooop/go/bin/swag", backupPanelDir); err != nil {
global.LOG.Errorf("snapshot backup 1panel failed, err: %v", err)
return err
}
}
if _, err := os.Stat("/etc/systemd/system/1panel.service"); err == nil {
if err := fileOp.CopyFile("/etc/systemd/system/1panel.service", backupPanelDir); err != nil {
global.LOG.Errorf("snapshot backup 1panel.service failed, err: %v", err)
return err
}
}
if _, err := os.Stat("/usr/local/bin/1panelctl"); err == nil {
if err := fileOp.CopyFile("/usr/local/bin/1panelctl", backupPanelDir); err != nil {
global.LOG.Errorf("snapshot backup 1panelctl failed, err: %v", err)
return err
}
}
if _, err := os.Stat(global.CONF.System.DataDir); err == nil {
if err := fileOp.Compress([]string{global.CONF.System.DataDir}, backupPanelDir, "1panel_data.tar.gz", files.TarGz); err != nil {
global.LOG.Errorf("snapshot backup 1panel data %s failed, err: %v", global.CONF.System.DataDir, err)
return err
}
}
if err := fileOp.Compress([]string{rootDir}, fmt.Sprintf("%s/system", localDir), fmt.Sprintf("1panel_backup_%s.tar.gz", timeNow), files.TarGz); err != nil {
return err
}
snap := model.Snapshot{
Name: "1panel_backup_" + timeNow,
Description: req.Description,
BackupType: req.BackupType,
Status: constant.StatusWaiting,
}
_ = snapshotRepo.Create(&snap)
go func() {
localPath := fmt.Sprintf("%s/system/1panel_backup_%s.tar.gz", localDir, timeNow)
if ok, err := backupAccont.Upload(localPath, fmt.Sprintf("system_snapshot/1panel_backup_%s.tar.gz", timeNow)); err != nil || !ok {
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
global.LOG.Errorf("upload snapshot to %s failed, err: %v", backup.Type, err)
return
}
snap.Status = constant.StatusSuccess
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusSuccess})
global.LOG.Infof("upload snapshot to %s success", backup.Type)
}()
return nil
}