mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-24 11:41:59 +08:00
feat: 完成 mysql 导入备份功能
This commit is contained in:
@@ -47,6 +47,50 @@ func (b *BaseApi) UpdateMysql(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) UploadMysqlFiles(c *gin.Context) {
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
files := form.File["file"]
|
||||
|
||||
mysqlName, ok := c.Params.Get("mysqlName")
|
||||
if !ok {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error mysqlName in path"))
|
||||
return
|
||||
}
|
||||
if err := mysqlService.UpFile(mysqlName, files); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) MysqlUpList(c *gin.Context) {
|
||||
var req dto.SearchDBWithPage
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
total, list, err := mysqlService.SearchUpListWithPage(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: list,
|
||||
Total: total,
|
||||
})
|
||||
}
|
||||
|
||||
func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
|
||||
var req []dto.MysqlVariablesUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -66,6 +66,15 @@ func (c *BackupRepo) WithByDetailName(detailName string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *BackupRepo) WithByFileName(fileName string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
if len(fileName) == 0 {
|
||||
return g
|
||||
}
|
||||
return g.Where("file_name = ?", fileName)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *BackupRepo) List(opts ...DBOption) ([]model.BackupAccount, error) {
|
||||
var ops []model.BackupAccount
|
||||
db := global.DB.Model(&model.BackupAccount{})
|
||||
|
||||
@@ -78,6 +78,10 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
app, err := mysqlRepo.LoadBaseInfoByName(cronjob.Database)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if cronjob.KeepLocal || cronjob.Type != "LOCAL" {
|
||||
backupLocal, err := backupRepo.Get(commonRepo.WithByType("LOCAL"))
|
||||
if err != nil {
|
||||
@@ -94,7 +98,7 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
|
||||
if cronjob.Type == "database" {
|
||||
fileName = fmt.Sprintf("db_%s_%s.sql.gz", cronjob.DBName, time.Now().Format("20060102150405"))
|
||||
backupDir = fmt.Sprintf("database/%s/%s", cronjob.Database, cronjob.DBName)
|
||||
backupDir = fmt.Sprintf("database/%s/%s/%s", app.Key, cronjob.Database, cronjob.DBName)
|
||||
err = backupMysql(backup.Type, baseDir, backupDir, cronjob.Database, cronjob.DBName, fileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -161,8 +165,24 @@ func (u *CronjobService) HandleRmExpired(backType, baseDir, backupDir string, cr
|
||||
global.LOG.Errorf("read dir %s failed, err: %v", baseDir+"/"+backupDir, err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(files)-int(cronjob.RetainCopies); i++ {
|
||||
_ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name())
|
||||
if len(files) == 0 {
|
||||
return
|
||||
}
|
||||
if cronjob.Type == "database" {
|
||||
dbCopies := uint64(0)
|
||||
for i := len(files) - 1; i >= 0; i-- {
|
||||
if strings.HasPrefix(files[i].Name(), "db_") {
|
||||
dbCopies++
|
||||
if dbCopies > cronjob.RetainCopies {
|
||||
_ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name())
|
||||
_ = backupRepo.DeleteRecord(backupRepo.WithByFileName(files[i].Name()))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < len(files)-int(cronjob.RetainCopies); i++ {
|
||||
_ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name())
|
||||
}
|
||||
}
|
||||
records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID)))
|
||||
if len(records) > int(cronjob.RetainCopies) {
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,6 +34,8 @@ type IMysqlService interface {
|
||||
ChangeInfo(info dto.ChangeDBInfo) error
|
||||
UpdateVariables(mysqlName string, updatas []dto.MysqlVariablesUpdate) error
|
||||
|
||||
UpFile(mysqlName string, files []*multipart.FileHeader) error
|
||||
SearchUpListWithPage(req dto.SearchDBWithPage) (int64, interface{}, error)
|
||||
Backup(db dto.BackupDB) error
|
||||
Recover(db dto.RecoverDB) error
|
||||
|
||||
@@ -59,8 +63,88 @@ func (u *MysqlService) SearchWithPage(search dto.SearchDBWithPage) (int64, inter
|
||||
return total, dtoMysqls, err
|
||||
}
|
||||
|
||||
func (u *MysqlService) SearchUpListWithPage(req dto.SearchDBWithPage) (int64, interface{}, error) {
|
||||
var (
|
||||
list []dto.RedisBackupRecords
|
||||
backDatas []dto.RedisBackupRecords
|
||||
)
|
||||
redisInfo, err := mysqlRepo.LoadBaseInfoByName(req.MysqlName)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
backupLocal, err := backupRepo.Get(commonRepo.WithByType("LOCAL"))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
localDir, err := loadLocalDir(backupLocal)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
uploadDir := fmt.Sprintf("%s/database/%s/%s/upload", localDir, redisInfo.Key, redisInfo.Name)
|
||||
if _, err := os.Stat(uploadDir); err != nil {
|
||||
return 0, list, nil
|
||||
}
|
||||
_ = filepath.Walk(uploadDir, func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() {
|
||||
list = append(list, dto.RedisBackupRecords{
|
||||
CreatedAt: info.ModTime().Format("2006-01-02 15:04:05"),
|
||||
Size: int(info.Size()),
|
||||
FileDir: uploadDir,
|
||||
FileName: info.Name(),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
if start > total {
|
||||
backDatas = make([]dto.RedisBackupRecords, 0)
|
||||
} else {
|
||||
if end >= total {
|
||||
end = total
|
||||
}
|
||||
backDatas = list[start:end]
|
||||
}
|
||||
return int64(total), backDatas, nil
|
||||
}
|
||||
|
||||
func (u *MysqlService) UpFile(mysqlName string, files []*multipart.FileHeader) error {
|
||||
backupLocal, err := backupRepo.Get(commonRepo.WithByType("LOCAL"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app, err := mysqlRepo.LoadBaseInfoByName(mysqlName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localDir, err := loadLocalDir(backupLocal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dstDir := fmt.Sprintf("%s/database/%s/%s/upload", localDir, app.Key, mysqlName)
|
||||
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dstDir, os.ModePerm); err != nil {
|
||||
if err != nil {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, file := range files {
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
out, err := os.Create(dstDir + "/" + file.Filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *MysqlService) ListDBByVersion(name string) ([]string, error) {
|
||||
mysqls, err := mysqlRepo.List(commonRepo.WithByName(name))
|
||||
mysqls, err := mysqlRepo.List(mysqlRepo.WithByMysqlName(name))
|
||||
var dbNames []string
|
||||
for _, mysql := range mysqls {
|
||||
dbNames = append(dbNames, mysql.Name)
|
||||
@@ -128,11 +212,15 @@ func (u *MysqlService) Backup(db dto.BackupDB) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app, err := mysqlRepo.LoadBaseInfoByName(db.MysqlName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localDir, err := loadLocalDir(backupLocal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
backupDir := fmt.Sprintf("database/%s/%s", db.MysqlName, db.DBName)
|
||||
backupDir := fmt.Sprintf("database/%s/%s/%s", app.Key, db.MysqlName, db.DBName)
|
||||
fileName := fmt.Sprintf("%s_%s.sql.gz", db.DBName, time.Now().Format("20060102150405"))
|
||||
if err := backupMysql("LOCAL", localDir, backupDir, db.MysqlName, db.DBName, fileName); err != nil {
|
||||
return err
|
||||
|
||||
@@ -24,6 +24,8 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) {
|
||||
withRecordRouter.POST("", baseApi.CreateMysql)
|
||||
withRecordRouter.PUT("/:id", baseApi.UpdateMysql)
|
||||
withRecordRouter.POST("/backup", baseApi.BackupMysql)
|
||||
withRecordRouter.POST("/uplist", baseApi.MysqlUpList)
|
||||
withRecordRouter.POST("/uplist/upload/:mysqlName", baseApi.UploadMysqlFiles)
|
||||
withRecordRouter.POST("/recover", baseApi.RecoverMysql)
|
||||
withRecordRouter.POST("/backups/search", baseApi.SearchDBBackups)
|
||||
withRecordRouter.POST("/del", baseApi.DeleteMysql)
|
||||
|
||||
Reference in New Issue
Block a user