mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	远程升级API节点时自动上传边缘节点安装文件
This commit is contained in:
		@@ -5,6 +5,7 @@ import (
 | 
				
			|||||||
	"github.com/iwind/TeaGo/files"
 | 
						"github.com/iwind/TeaGo/files"
 | 
				
			||||||
	stringutil "github.com/iwind/TeaGo/utils/string"
 | 
						stringutil "github.com/iwind/TeaGo/utils/string"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var SharedDeployManager = NewDeployManager()
 | 
					var SharedDeployManager = NewDeployManager()
 | 
				
			||||||
@@ -12,9 +13,12 @@ var SharedDeployManager = NewDeployManager()
 | 
				
			|||||||
// DeployManager 节点部署文件管理器
 | 
					// DeployManager 节点部署文件管理器
 | 
				
			||||||
// 如果节点部署文件有变化,需要重启API节点以便于生效
 | 
					// 如果节点部署文件有变化,需要重启API节点以便于生效
 | 
				
			||||||
type DeployManager struct {
 | 
					type DeployManager struct {
 | 
				
			||||||
	dir         string
 | 
						dir string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nodeFiles   []*DeployFile
 | 
						nodeFiles   []*DeployFile
 | 
				
			||||||
	nsNodeFiles []*DeployFile
 | 
						nsNodeFiles []*DeployFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						locker sync.Mutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewDeployManager 获取新节点部署文件管理器
 | 
					// NewDeployManager 获取新节点部署文件管理器
 | 
				
			||||||
@@ -29,24 +33,27 @@ func NewDeployManager() *DeployManager {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// LoadNodeFiles 加载所有边缘节点文件
 | 
					// LoadNodeFiles 加载所有边缘节点文件
 | 
				
			||||||
func (this *DeployManager) LoadNodeFiles() []*DeployFile {
 | 
					func (this *DeployManager) LoadNodeFiles() []*DeployFile {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						defer this.locker.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(this.nodeFiles) > 0 {
 | 
						if len(this.nodeFiles) > 0 {
 | 
				
			||||||
		return this.nodeFiles
 | 
							return this.nodeFiles
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keyMap := map[string]*DeployFile{} // key => File
 | 
						var keyMap = map[string]*DeployFile{} // key => File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg := regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
 | 
						var reg = regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
 | 
				
			||||||
	for _, file := range files.NewFile(this.dir).List() {
 | 
						for _, file := range files.NewFile(this.dir).List() {
 | 
				
			||||||
		name := file.Name()
 | 
							var name = file.Name()
 | 
				
			||||||
		if !reg.MatchString(name) {
 | 
							if !reg.MatchString(name) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		matches := reg.FindStringSubmatch(name)
 | 
							var matches = reg.FindStringSubmatch(name)
 | 
				
			||||||
		osName := matches[1]
 | 
							var osName = matches[1]
 | 
				
			||||||
		arch := matches[2]
 | 
							var arch = matches[2]
 | 
				
			||||||
		version := matches[3]
 | 
							var version = matches[3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key := osName + "_" + arch
 | 
							var key = osName + "_" + arch
 | 
				
			||||||
		oldFile, ok := keyMap[key]
 | 
							oldFile, ok := keyMap[key]
 | 
				
			||||||
		if ok && stringutil.VersionCompare(oldFile.Version, version) > 0 {
 | 
							if ok && stringutil.VersionCompare(oldFile.Version, version) > 0 {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -59,7 +66,7 @@ func (this *DeployManager) LoadNodeFiles() []*DeployFile {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result := []*DeployFile{}
 | 
						var result = []*DeployFile{}
 | 
				
			||||||
	for _, v := range keyMap {
 | 
						for _, v := range keyMap {
 | 
				
			||||||
		result = append(result, v)
 | 
							result = append(result, v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -81,24 +88,27 @@ func (this *DeployManager) FindNodeFile(os string, arch string) *DeployFile {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// LoadNSNodeFiles 加载所有NS节点安装文件
 | 
					// LoadNSNodeFiles 加载所有NS节点安装文件
 | 
				
			||||||
func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
 | 
					func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						defer this.locker.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(this.nsNodeFiles) > 0 {
 | 
						if len(this.nsNodeFiles) > 0 {
 | 
				
			||||||
		return this.nsNodeFiles
 | 
							return this.nsNodeFiles
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keyMap := map[string]*DeployFile{} // key => File
 | 
						var keyMap = map[string]*DeployFile{} // key => File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg := regexp.MustCompile(`^edge-dns-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
 | 
						var reg = regexp.MustCompile(`^edge-dns-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
 | 
				
			||||||
	for _, file := range files.NewFile(this.dir).List() {
 | 
						for _, file := range files.NewFile(this.dir).List() {
 | 
				
			||||||
		name := file.Name()
 | 
							var name = file.Name()
 | 
				
			||||||
		if !reg.MatchString(name) {
 | 
							if !reg.MatchString(name) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		matches := reg.FindStringSubmatch(name)
 | 
							var matches = reg.FindStringSubmatch(name)
 | 
				
			||||||
		osName := matches[1]
 | 
							var osName = matches[1]
 | 
				
			||||||
		arch := matches[2]
 | 
							var arch = matches[2]
 | 
				
			||||||
		version := matches[3]
 | 
							var version = matches[3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key := osName + "_" + arch
 | 
							var key = osName + "_" + arch
 | 
				
			||||||
		oldFile, ok := keyMap[key]
 | 
							oldFile, ok := keyMap[key]
 | 
				
			||||||
		if ok && stringutil.VersionCompare(oldFile.Version, version) > 0 {
 | 
							if ok && stringutil.VersionCompare(oldFile.Version, version) > 0 {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -111,7 +121,7 @@ func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result := []*DeployFile{}
 | 
						var result = []*DeployFile{}
 | 
				
			||||||
	for _, v := range keyMap {
 | 
						for _, v := range keyMap {
 | 
				
			||||||
		result = append(result, v)
 | 
							result = append(result, v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -130,3 +140,12 @@ func (this *DeployManager) FindNSNodeFile(os string, arch string) *DeployFile {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reload 重置缓存
 | 
				
			||||||
 | 
					func (this *DeployManager) Reload() {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						defer this.locker.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.nodeFiles = nil
 | 
				
			||||||
 | 
						this.nsNodeFiles = nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
 | 
						teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/db/models"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/db/models"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/installers"
 | 
				
			||||||
	rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
 | 
						rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
 | 
				
			||||||
	executils "github.com/TeaOSLab/EdgeAPI/internal/utils/exec"
 | 
						executils "github.com/TeaOSLab/EdgeAPI/internal/utils/exec"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
@@ -481,3 +482,106 @@ func (this *APINodeService) UploadAPINodeFile(ctx context.Context, req *pb.Uploa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return &pb.UploadAPINodeFileResponse{}, nil
 | 
						return &pb.UploadAPINodeFileResponse{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UploadDeployFileToAPINode 上传节点安装文件
 | 
				
			||||||
 | 
					func (this *APINodeService) UploadDeployFileToAPINode(ctx context.Context, req *pb.UploadDeployFileToAPINodeRequest) (*pb.RPCSuccess, error) {
 | 
				
			||||||
 | 
						_, err := this.ValidateAdmin(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var targetDir = Tea.Root + "/deploy/"
 | 
				
			||||||
 | 
						var targetTmpFile = targetDir + "/" + req.Filename + ".tmp"
 | 
				
			||||||
 | 
						var targetFile = targetDir + "/" + req.Filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if req.IsFirstChunk {
 | 
				
			||||||
 | 
							_ = os.Remove(targetTmpFile)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(req.ChunkData) > 0 {
 | 
				
			||||||
 | 
							err = func() error {
 | 
				
			||||||
 | 
								var flags = os.O_CREATE | os.O_WRONLY
 | 
				
			||||||
 | 
								if req.IsFirstChunk {
 | 
				
			||||||
 | 
									flags |= os.O_TRUNC
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									flags |= os.O_APPEND
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								fp, err := os.OpenFile(targetTmpFile, flags, 0666)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									_ = fp.Close()
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								_, err = fp.Write(req.ChunkData)
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, errors.New("write file failed: " + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if req.IsLastChunk {
 | 
				
			||||||
 | 
							// 检查SUM
 | 
				
			||||||
 | 
							fp, err := os.Open(targetTmpFile)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var hash = md5.New()
 | 
				
			||||||
 | 
							_, err = io.Copy(hash, fp)
 | 
				
			||||||
 | 
							_ = fp.Close()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var tmpSum = fmt.Sprintf("%x", hash.Sum(nil))
 | 
				
			||||||
 | 
							if tmpSum != req.Sum {
 | 
				
			||||||
 | 
								_ = os.Remove(targetTmpFile)
 | 
				
			||||||
 | 
								return nil, errors.New("check sum failed")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 正式改名
 | 
				
			||||||
 | 
							err = os.Rename(targetTmpFile, targetFile)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, errors.New("rename failed: " + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 重载数据
 | 
				
			||||||
 | 
							installers.SharedDeployManager.Reload()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FindLatestDeployFiles 查找已有节点安装文件信息
 | 
				
			||||||
 | 
					func (this *APINodeService) FindLatestDeployFiles(ctx context.Context, req *pb.FindLatestDeployFilesRequest) (*pb.FindLatestDeployFilesResponse, error) {
 | 
				
			||||||
 | 
						_, err := this.ValidateAdmin(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var pbNodeFiles = []*pb.FindLatestDeployFilesResponse_DeployFile{}
 | 
				
			||||||
 | 
						var nodeFiles = installers.SharedDeployManager.LoadNodeFiles()
 | 
				
			||||||
 | 
						for _, nodeFile := range nodeFiles {
 | 
				
			||||||
 | 
							pbNodeFiles = append(pbNodeFiles, &pb.FindLatestDeployFilesResponse_DeployFile{
 | 
				
			||||||
 | 
								Os:      nodeFile.OS,
 | 
				
			||||||
 | 
								Arch:    nodeFile.Arch,
 | 
				
			||||||
 | 
								Version: nodeFile.Version,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var pbNSNodeFiles = []*pb.FindLatestDeployFilesResponse_DeployFile{}
 | 
				
			||||||
 | 
						var nsNodeFiles = installers.SharedDeployManager.LoadNSNodeFiles()
 | 
				
			||||||
 | 
						for _, nodeFile := range nsNodeFiles {
 | 
				
			||||||
 | 
							pbNSNodeFiles = append(pbNSNodeFiles, &pb.FindLatestDeployFilesResponse_DeployFile{
 | 
				
			||||||
 | 
								Os:      nodeFile.OS,
 | 
				
			||||||
 | 
								Arch:    nodeFile.Arch,
 | 
				
			||||||
 | 
								Version: nodeFile.Version,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.FindLatestDeployFilesResponse{
 | 
				
			||||||
 | 
							NodeDeployFiles:   pbNodeFiles,
 | 
				
			||||||
 | 
							NsNodeDeployFiles: pbNSNodeFiles,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user