mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-03 06:40:26 +08:00
实现基础的智能调度
This commit is contained in:
@@ -12,4 +12,5 @@ dbs:
|
||||
|
||||
|
||||
fields:
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables" ]
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified" ]
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
type DNSTaskType = string
|
||||
|
||||
const (
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange" // 集群节点、服务发生变化
|
||||
DNSTaskTypeClusterNodesChange DNSTaskType = "clusterNodesChange" // 集群中节点发生变化
|
||||
DNSTaskTypeClusterRemoveDomain DNSTaskType = "clusterRemoveDomain" // 从集群中移除域名
|
||||
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
|
||||
DNSTaskTypeServerChange DNSTaskType = "serverChange"
|
||||
|
||||
@@ -52,7 +52,9 @@ const (
|
||||
|
||||
MessageTypeReportNodeInactive MessageType = "ReportNodeInactive" // 区域监控节点节点不活跃
|
||||
MessageTypeReportNodeActive MessageType = "ReportNodeActive" // 区域监控节点活跃
|
||||
MessageTypeConnectivity MessageType = "Connectivity"
|
||||
MessageTypeConnectivity MessageType = "Connectivity" // 连通性
|
||||
MessageTypeNodeSchedule MessageType = "NodeSchedule" // 节点调度信息
|
||||
MessageTypeNodeOfflineDay MessageType = "NodeOfflineDay" // 节点到下线日期
|
||||
)
|
||||
|
||||
type MessageDAO dbs.DAO
|
||||
|
||||
63
internal/db/models/node_action_dao.go
Normal file
63
internal/db/models/node_action_dao.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NodeActionStateEnabled = 1 // 已启用
|
||||
NodeActionStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NodeActionDAO dbs.DAO
|
||||
|
||||
func NewNodeActionDAO() *NodeActionDAO {
|
||||
return dbs.NewDAO(&NodeActionDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNodeActions",
|
||||
Model: new(NodeAction),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NodeActionDAO)
|
||||
}
|
||||
|
||||
var SharedNodeActionDAO *NodeActionDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNodeActionDAO = NewNodeActionDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNodeAction 启用条目
|
||||
func (this *NodeActionDAO) EnableNodeAction(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodeActionStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNodeAction 禁用条目
|
||||
func (this *NodeActionDAO) DisableNodeAction(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodeActionStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNodeAction 查找启用中的条目
|
||||
func (this *NodeActionDAO) FindEnabledNodeAction(tx *dbs.Tx, id int64) (*NodeAction, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NodeActionStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NodeAction), err
|
||||
}
|
||||
6
internal/db/models/node_action_dao_test.go
Normal file
6
internal/db/models/node_action_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
32
internal/db/models/node_action_model.go
Normal file
32
internal/db/models/node_action_model.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NodeAction 节点智能调度设置
|
||||
type NodeAction struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
NodeId uint64 `field:"nodeId"` // 节点ID
|
||||
Role string `field:"role"` // 角色
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
Action dbs.JSON `field:"action"` // 动作
|
||||
Duration dbs.JSON `field:"duration"` // 持续时间
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NodeActionOperator struct {
|
||||
Id any // ID
|
||||
NodeId any // 节点ID
|
||||
Role any // 角色
|
||||
IsOn any // 是否启用
|
||||
Conds any // 条件
|
||||
Action any // 动作
|
||||
Duration any // 持续时间
|
||||
Order any // 排序
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNodeActionOperator() *NodeActionOperator {
|
||||
return &NodeActionOperator{}
|
||||
}
|
||||
1
internal/db/models/node_action_model_ext.go
Normal file
1
internal/db/models/node_action_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -1550,7 +1550,7 @@ func (this *NodeDAO) FindAllEnabledNodesDNSWithClusterId(tx *dbs.Tx, clusterId i
|
||||
Attr("isOn", true).
|
||||
Attr("isUp", true).
|
||||
Attr("isInstalled", isInstalled).
|
||||
Result("id", "name", "dnsRoutes", "isOn").
|
||||
Result("id", "name", "dnsRoutes", "isOn", "offlineDay", "actionStatus", "isBackupForCluster", "isBackupForGroup", "backupIPs", "clusterId", "groupId").
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
@@ -1575,7 +1575,7 @@ func (this *NodeDAO) FindEnabledNodeDNS(tx *dbs.Tx, nodeId int64) (*Node, error)
|
||||
one, err := this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Pk(nodeId).
|
||||
Result("id", "name", "dnsRoutes", "clusterId", "isOn").
|
||||
Result("id", "name", "dnsRoutes", "clusterId", "isOn", "offlineDay", "isBackupForCluster", "isBackupForGroup", "actionStatus").
|
||||
Find()
|
||||
if one == nil {
|
||||
return nil, err
|
||||
|
||||
@@ -18,3 +18,8 @@ func (this *NodeDAO) loadServersFromCluster(tx *dbs.Tx, clusterId int64, serverI
|
||||
func (this *NodeDAO) composeExtConfig(tx *dbs.Tx, config *nodeconfigs.NodeConfig, clusterIds []int64, cacheMap *utils.CacheMap) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckNodeIPAddresses 检查节点IP地址
|
||||
func (this *NodeDAO) CheckNodeIPAddresses(tx *dbs.Tx, node *Node) (shouldSkip bool, shouldOverwrite bool, ipAddressStrings []string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@ type Node struct {
|
||||
DnsResolver dbs.JSON `field:"dnsResolver"` // DNS解析器
|
||||
EnableIPLists bool `field:"enableIPLists"` // 启用IP名单
|
||||
ApiNodeAddrs dbs.JSON `field:"apiNodeAddrs"` // API节点地址
|
||||
OfflineDay string `field:"offlineDay"` // 下线日期YYYYMMDD
|
||||
OfflineIsNotified bool `field:"offlineIsNotified"` // 下线是否已通知
|
||||
IsBackupForCluster bool `field:"isBackupForCluster"` // 是否为集群备用节点
|
||||
IsBackupForGroup bool `field:"isBackupForGroup"` // 是否为分组备用节点
|
||||
BackupIPs dbs.JSON `field:"backupIPs"` // 备用IP
|
||||
ActionStatus dbs.JSON `field:"actionStatus"` // 当前动作配置
|
||||
}
|
||||
|
||||
type NodeOperator struct {
|
||||
@@ -85,6 +91,12 @@ type NodeOperator struct {
|
||||
DnsResolver any // DNS解析器
|
||||
EnableIPLists any // 启用IP名单
|
||||
ApiNodeAddrs any // API节点地址
|
||||
OfflineDay any // 下线日期YYYYMMDD
|
||||
OfflineIsNotified any // 下线是否已通知
|
||||
IsBackupForCluster any // 是否为集群备用节点
|
||||
IsBackupForGroup any // 是否为分组备用节点
|
||||
BackupIPs any // 备用IP
|
||||
ActionStatus any // 当前动作配置
|
||||
}
|
||||
|
||||
func NewNodeOperator() *NodeOperator {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@@ -16,7 +17,7 @@ func (this *Node) DecodeInstallStatus() (*NodeInstallStatus, error) {
|
||||
if len(this.InstallStatus) == 0 {
|
||||
return NewNodeInstallStatus(), nil
|
||||
}
|
||||
status := &NodeInstallStatus{}
|
||||
var status = &NodeInstallStatus{}
|
||||
err := json.Unmarshal(this.InstallStatus, status)
|
||||
if err != nil {
|
||||
return NewNodeInstallStatus(), err
|
||||
@@ -37,7 +38,7 @@ func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
|
||||
if len(this.Status) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
status := &nodeconfigs.NodeStatus{}
|
||||
var status = &nodeconfigs.NodeStatus{}
|
||||
err := json.Unmarshal(this.Status, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -47,7 +48,7 @@ func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
|
||||
|
||||
// DNSRouteCodes 所有的DNS线路
|
||||
func (this *Node) DNSRouteCodes() map[int64][]string {
|
||||
routes := map[int64][]string{} // domainId => routes
|
||||
var routes = map[int64][]string{} // domainId => routes
|
||||
if len(this.DnsRoutes) == 0 {
|
||||
return routes
|
||||
}
|
||||
@@ -61,7 +62,7 @@ func (this *Node) DNSRouteCodes() map[int64][]string {
|
||||
|
||||
// DNSRouteCodesForDomainId DNS线路
|
||||
func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error) {
|
||||
routes := map[int64][]string{} // domainId => routes
|
||||
var routes = map[int64][]string{} // domainId => routes
|
||||
if len(this.DnsRoutes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error)
|
||||
|
||||
// DecodeConnectedAPINodeIds 连接的API
|
||||
func (this *Node) DecodeConnectedAPINodeIds() ([]int64, error) {
|
||||
apiNodeIds := []int64{}
|
||||
var apiNodeIds = []int64{}
|
||||
if IsNotNull(this.ConnectedAPINodes) {
|
||||
err := json.Unmarshal(this.ConnectedAPINodes, &apiNodeIds)
|
||||
if err != nil {
|
||||
@@ -214,3 +215,8 @@ func (this *Node) DecodeAPINodeAddrs() []*serverconfigs.NetworkAddressConfig {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CheckIsOffline 检查是否已经离线
|
||||
func (this *Node) CheckIsOffline() bool {
|
||||
return len(this.OfflineDay) > 0 && this.OfflineDay < timeutil.Format("Ymd")
|
||||
}
|
||||
|
||||
9
internal/db/models/node_model_ext_schdule.go
Normal file
9
internal/db/models/node_model_ext_schdule.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
// HasScheduleSettings 检查是否设置了调度
|
||||
func (this *Node) HasScheduleSettings() bool {
|
||||
return false
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package stats
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
@@ -84,7 +84,9 @@ func (this *NodeTrafficDailyStatDAO) IncreaseDailyStat(tx *dbs.Tx, clusterId int
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
// 触发钩子
|
||||
return this.increaseDailyStatHook(tx, role, nodeId)
|
||||
}
|
||||
|
||||
// FindDailyStats 获取日期之间统计
|
||||
14
internal/db/models/node_traffic_daily_stat_dao_ext.go
Normal file
14
internal/db/models/node_traffic_daily_stat_dao_ext.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
// 增加日统计Hook
|
||||
func (this *NodeTrafficDailyStatDAO) increaseDailyStatHook(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package stats
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -1,4 +1,4 @@
|
||||
package stats
|
||||
package models
|
||||
|
||||
// NodeTrafficDailyStat 总的流量统计(按天)
|
||||
type NodeTrafficDailyStat struct {
|
||||
1
internal/db/models/node_traffic_daily_stat_model_ext.go
Normal file
1
internal/db/models/node_traffic_daily_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -37,11 +37,15 @@ func init() {
|
||||
|
||||
// CreateValue 创建值
|
||||
func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconfigs.NodeRole, nodeId int64, item string, valueJSON []byte, createdAt int64) error {
|
||||
if len(valueJSON) == 0 {
|
||||
return errors.New("'valueJSON' should not be nil")
|
||||
}
|
||||
|
||||
var day = timeutil.FormatTime("Ymd", createdAt)
|
||||
var hour = timeutil.FormatTime("YmdH", createdAt)
|
||||
var minute = timeutil.FormatTime("YmdHi", createdAt)
|
||||
|
||||
return this.Query(tx).
|
||||
err := this.Query(tx).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
"role": role,
|
||||
@@ -55,6 +59,17 @@ func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconf
|
||||
}, maps.Map{
|
||||
"value": valueJSON,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 触发钩子
|
||||
err = this.nodeValueHook(tx, role, nodeId, item, valueJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean 清除数据
|
||||
@@ -324,7 +339,7 @@ func (this *NodeValueDAO) SumNodeClusterValues(tx *dbs.Tx, role string, clusterI
|
||||
|
||||
// FindLatestNodeValue 获取最近一条数据
|
||||
func (this *NodeValueDAO) FindLatestNodeValue(tx *dbs.Tx, role string, nodeId int64, item string) (*NodeValue, error) {
|
||||
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(60))
|
||||
var fromMinute = timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(60))
|
||||
|
||||
one, err := this.Query(tx).
|
||||
Attr("role", role).
|
||||
|
||||
14
internal/db/models/node_value_dao_ext.go
Normal file
14
internal/db/models/node_value_dao_ext.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
// 节点值变更Hook
|
||||
func (this *NodeValueDAO) nodeValueHook(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64, item nodeconfigs.NodeValueItem, valueJSON []byte) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package stats
|
||||
@@ -1,10 +1,11 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package dnsclients
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// FindProvider 查找服务商实例
|
||||
func FindProvider(providerType ProviderType, providerId int64) ProviderInterface {
|
||||
|
||||
@@ -472,13 +472,14 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
var nodeKeys = []string{}
|
||||
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
|
||||
for _, node := range nodes {
|
||||
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
||||
shouldSkip, shouldOverwrite, ipAddressesStrings, err := models.SharedNodeDAO.CheckNodeIPAddresses(tx, node)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, false, false, err
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
if shouldSkip {
|
||||
continue
|
||||
}
|
||||
|
||||
routeCodes, err := node.DNSRouteCodesForDomainId(int64(cluster.DnsDomainId))
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, false, false, err
|
||||
@@ -491,7 +492,16 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, route := range routeCodes {
|
||||
|
||||
if !shouldOverwrite {
|
||||
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, false, false, err
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ipAddress := range ipAddresses {
|
||||
// 检查专属节点
|
||||
if !ipAddress.IsValidInCluster(clusterId) {
|
||||
@@ -505,6 +515,16 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
if net.ParseIP(ip) == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ipAddressesStrings = append(ipAddressesStrings, ip)
|
||||
}
|
||||
}
|
||||
if len(ipAddressesStrings) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, route := range routeCodes {
|
||||
for _, ip := range ipAddressesStrings {
|
||||
var key = ip + "_" + route
|
||||
nodeKeys = append(nodeKeys, key)
|
||||
record, ok := nodeRecordMapping[key]
|
||||
|
||||
@@ -62,7 +62,7 @@ func (this *DNSTaskService) FindAllDoingDNSTasks(ctx context.Context, req *pb.Fi
|
||||
}
|
||||
|
||||
switch task.Type {
|
||||
case dns.DNSTaskTypeClusterChange, dns.DNSTaskTypeClusterRemoveDomain:
|
||||
case dns.DNSTaskTypeClusterChange, dns.DNSTaskTypeClusterNodesChange, dns.DNSTaskTypeClusterRemoveDomain:
|
||||
clusterName, err := models.SharedNodeClusterDAO.FindNodeClusterName(tx, int64(task.ClusterId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -384,6 +384,9 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
|
||||
NodeRegion: pbRegion,
|
||||
DnsRoutes: pbRoutes,
|
||||
Level: int32(node.Level),
|
||||
OfflineDay: node.OfflineDay,
|
||||
IsBackupForCluster: node.IsBackupForCluster,
|
||||
IsBackupForGroup: node.IsBackupForGroup,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -683,6 +686,9 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
|
||||
DnsRoutes: pbRoutes,
|
||||
EnableIPLists: node.EnableIPLists,
|
||||
ApiNodeAddrsJSON: node.ApiNodeAddrs,
|
||||
OfflineDay: node.OfflineDay,
|
||||
IsBackupForCluster: node.IsBackupForCluster,
|
||||
IsBackupForGroup: node.IsBackupForGroup,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
@@ -1397,12 +1403,15 @@ func (this *NodeService) FindAllEnabledNodesDNSWithNodeClusterId(ctx context.Con
|
||||
continue
|
||||
}
|
||||
result = append(result, &pb.NodeDNSInfo{
|
||||
Id: int64(node.Id),
|
||||
Name: node.Name,
|
||||
IpAddr: ip,
|
||||
NodeIPAddressId: int64(ipAddress.Id),
|
||||
Routes: pbRoutes,
|
||||
NodeClusterId: req.NodeClusterId,
|
||||
Id: int64(node.Id),
|
||||
Name: node.Name,
|
||||
IpAddr: ip,
|
||||
NodeIPAddressId: int64(ipAddress.Id),
|
||||
Routes: pbRoutes,
|
||||
NodeClusterId: req.NodeClusterId,
|
||||
IsBackupForCluster: node.IsBackupForCluster,
|
||||
IsBackupForGroup: node.IsBackupForGroup,
|
||||
IsOffline: node.CheckIsOffline(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1497,6 +1506,9 @@ func (this *NodeService) FindEnabledNodeDNS(ctx context.Context, req *pb.FindEna
|
||||
NodeClusterDNSName: clusterDNS.DnsName,
|
||||
DnsDomainId: dnsDomainId,
|
||||
DnsDomainName: dnsDomainName,
|
||||
IsBackupForCluster: node.IsBackupForCluster,
|
||||
IsBackupForGroup: node.IsBackupForGroup,
|
||||
IsOffline: node.CheckIsOffline(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -2097,6 +2109,9 @@ func (this *NodeService) FindEnabledNodeConfigInfo(ctx context.Context, req *pb.
|
||||
// ddos protection
|
||||
result.HasDDoSProtection = node.HasDDoSProtection()
|
||||
|
||||
// schedule
|
||||
result.HasScheduleSettings = node.HasScheduleSettings()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
||||
21
internal/rpc/services/service_node_ext.go
Normal file
21
internal/rpc/services/service_node_ext.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
func (this *NodeService) FindNodeScheduleInfo(ctx context.Context, req *pb.FindNodeScheduleInfoRequest) (*pb.FindNodeScheduleInfoResponse, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
func (this *NodeService) UpdateNodeScheduleInfo(ctx context.Context, req *pb.UpdateNodeScheduleInfoRequest) (*pb.RPCSuccess, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
func (this *NodeService) ResetNodeActionStatus(ctx context.Context, req *pb.ResetNodeActionStatusRequest) (*pb.RPCSuccess, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (this *ServerDailyStatService) UploadServerDailyStats(ctx context.Context,
|
||||
|
||||
// 节点流量
|
||||
if nodeId > 0 {
|
||||
err = stats.SharedNodeTrafficDailyStatDAO.IncreaseDailyStat(tx, clusterId, role, nodeId, timeutil.FormatTime("Ymd", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
|
||||
err = models.SharedNodeTrafficDailyStatDAO.IncreaseDailyStat(tx, clusterId, role, nodeId, timeutil.FormatTime("Ymd", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
|
||||
}
|
||||
|
||||
// 当月总流量
|
||||
monthlyTrafficStat, err := stats.SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, req.NodeId, timeutil.Format("Ym01"), timeutil.Format("Ym31"))
|
||||
monthlyTrafficStat, err := models.SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, req.NodeId, timeutil.Format("Ym01"), timeutil.Format("Ym31"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -335,7 +335,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
|
||||
|
||||
// 按日流量统计
|
||||
var dayFrom = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := stats.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
|
||||
dailyTrafficStats, err := models.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -67267,7 +67267,7 @@
|
||||
"name": "edgeNSDomains",
|
||||
"engine": "InnoDB",
|
||||
"charset": "utf8mb4_general_ci",
|
||||
"definition": "CREATE TABLE `edgeNSDomains` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `name` varchar(255) DEFAULT NULL COMMENT '域名',\n `groupIds` json DEFAULT NULL COMMENT '分组ID',\n `tsig` json DEFAULT NULL COMMENT 'TSIG配置',\n `verifyTXT` varchar(64) DEFAULT NULL COMMENT '验证用的TXT',\n `verifyExpiresAt` bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `status` varchar(64) DEFAULT 'none' COMMENT '状态:none|verified',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `userId` (`userId`),\n KEY `name` (`name`),\n KEY `version` (`version`) USING BTREE,\n KEY `status` (`status`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS域名'",
|
||||
"definition": "CREATE TABLE `edgeNSDomains` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `name` varchar(255) DEFAULT NULL COMMENT '域名',\n `groupIds` json DEFAULT NULL COMMENT '分组ID',\n `tsig` json DEFAULT NULL COMMENT 'TSIG配置',\n `verifyTXT` varchar(64) DEFAULT NULL COMMENT '验证用的TXT',\n `verifyExpiresAt` bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间',\n `recordsHealthCheck` json DEFAULT NULL COMMENT '记录健康检查设置',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `status` varchar(64) DEFAULT 'none' COMMENT '状态:none|verified',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `userId` (`userId`),\n KEY `name` (`name`),\n KEY `version` (`version`) USING BTREE,\n KEY `status` (`status`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS域名'",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -67305,6 +67305,10 @@
|
||||
"name": "verifyExpiresAt",
|
||||
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间'"
|
||||
},
|
||||
{
|
||||
"name": "recordsHealthCheck",
|
||||
"definition": "json COMMENT '记录健康检查设置'"
|
||||
},
|
||||
{
|
||||
"name": "createdAt",
|
||||
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '创建时间'"
|
||||
@@ -67653,7 +67657,7 @@
|
||||
"name": "edgeNSRecords",
|
||||
"engine": "InnoDB",
|
||||
"charset": "utf8mb4_general_ci",
|
||||
"definition": "CREATE TABLE `edgeNSRecords` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `domainId` int(11) unsigned DEFAULT '0' COMMENT '域名ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `description` varchar(512) DEFAULT NULL COMMENT '备注',\n `name` varchar(255) DEFAULT NULL COMMENT '记录名',\n `type` varchar(32) DEFAULT NULL COMMENT '类型',\n `value` varchar(4096) DEFAULT NULL COMMENT '值',\n `mxPriority` int(11) unsigned DEFAULT '0' COMMENT 'MX优先级',\n `srvPriority` int(11) unsigned DEFAULT '0' COMMENT 'SRV优先级',\n `srvWeight` int(11) unsigned DEFAULT '0' COMMENT 'SRV权重',\n `srvPort` int(11) unsigned DEFAULT '0' COMMENT 'SRV端口',\n `caaFlag` tinyint(1) unsigned DEFAULT '0' COMMENT 'CAA Flag',\n `caaTag` varchar(32) DEFAULT NULL COMMENT 'CAA TAG',\n `ttl` int(11) unsigned DEFAULT '0' COMMENT 'TTL(秒)',\n `weight` int(11) unsigned DEFAULT '0' COMMENT '权重',\n `routeIds` json DEFAULT NULL COMMENT '线路',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `domainId` (`domainId`),\n KEY `version` (`version`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS记录'",
|
||||
"definition": "CREATE TABLE `edgeNSRecords` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `domainId` int(11) unsigned DEFAULT '0' COMMENT '域名ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `description` varchar(512) DEFAULT NULL COMMENT '备注',\n `name` varchar(255) DEFAULT NULL COMMENT '记录名',\n `type` varchar(32) DEFAULT NULL COMMENT '类型',\n `value` varchar(4096) DEFAULT NULL COMMENT '值',\n `mxPriority` int(11) unsigned DEFAULT '0' COMMENT 'MX优先级',\n `srvPriority` int(11) unsigned DEFAULT '0' COMMENT 'SRV优先级',\n `srvWeight` int(11) unsigned DEFAULT '0' COMMENT 'SRV权重',\n `srvPort` int(11) unsigned DEFAULT '0' COMMENT 'SRV端口',\n `caaFlag` tinyint(1) unsigned DEFAULT '0' COMMENT 'CAA Flag',\n `caaTag` varchar(32) DEFAULT NULL COMMENT 'CAA TAG',\n `ttl` int(11) unsigned DEFAULT '0' COMMENT 'TTL(秒)',\n `weight` int(11) unsigned DEFAULT '0' COMMENT '权重',\n `routeIds` json DEFAULT NULL COMMENT '线路',\n `healthCheck` json DEFAULT NULL COMMENT '健康检查配置',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续上线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续离线次数',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `domainId` (`domainId`),\n KEY `version` (`version`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS记录'",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -67719,6 +67723,22 @@
|
||||
"name": "routeIds",
|
||||
"definition": "json COMMENT '线路'"
|
||||
},
|
||||
{
|
||||
"name": "healthCheck",
|
||||
"definition": "json COMMENT '健康检查配置'"
|
||||
},
|
||||
{
|
||||
"name": "countUp",
|
||||
"definition": "int(11) unsigned DEFAULT '0' COMMENT '连续上线次数'"
|
||||
},
|
||||
{
|
||||
"name": "countDown",
|
||||
"definition": "int(11) unsigned DEFAULT '0' COMMENT '连续离线次数'"
|
||||
},
|
||||
{
|
||||
"name": "isUp",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线'"
|
||||
},
|
||||
{
|
||||
"name": "createdAt",
|
||||
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '创建时间'"
|
||||
@@ -67992,6 +68012,61 @@
|
||||
],
|
||||
"records": []
|
||||
},
|
||||
{
|
||||
"name": "edgeNodeActions",
|
||||
"engine": "InnoDB",
|
||||
"charset": "utf8mb4_general_ci",
|
||||
"definition": "CREATE TABLE `edgeNodeActions` (\n `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `nodeId` bigint(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `role` varchar(16) DEFAULT NULL COMMENT '角色',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `conds` json DEFAULT NULL COMMENT '条件',\n `action` json DEFAULT NULL COMMENT '动作',\n `duration` json DEFAULT NULL COMMENT '持续时间',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点智能调度设置'",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"definition": "bigint(11) unsigned auto_increment COMMENT 'ID'"
|
||||
},
|
||||
{
|
||||
"name": "nodeId",
|
||||
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '节点ID'"
|
||||
},
|
||||
{
|
||||
"name": "role",
|
||||
"definition": "varchar(16) COMMENT '角色'"
|
||||
},
|
||||
{
|
||||
"name": "isOn",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用'"
|
||||
},
|
||||
{
|
||||
"name": "conds",
|
||||
"definition": "json COMMENT '条件'"
|
||||
},
|
||||
{
|
||||
"name": "action",
|
||||
"definition": "json COMMENT '动作'"
|
||||
},
|
||||
{
|
||||
"name": "duration",
|
||||
"definition": "json COMMENT '持续时间'"
|
||||
},
|
||||
{
|
||||
"name": "order",
|
||||
"definition": "int(11) unsigned DEFAULT '0' COMMENT '排序'"
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '状态'"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"name": "PRIMARY",
|
||||
"definition": "UNIQUE KEY `PRIMARY` (`id`) USING BTREE"
|
||||
},
|
||||
{
|
||||
"name": "nodeId",
|
||||
"definition": "KEY `nodeId` (`nodeId`) USING BTREE"
|
||||
}
|
||||
],
|
||||
"records": []
|
||||
},
|
||||
{
|
||||
"name": "edgeNodeClusterFirewallActions",
|
||||
"engine": "InnoDB",
|
||||
@@ -69041,7 +69116,7 @@
|
||||
"name": "edgeNodeThresholds",
|
||||
"engine": "InnoDB",
|
||||
"charset": "utf8mb4_general_ci",
|
||||
"definition": "CREATE TABLE `edgeNodeThresholds` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `role` varchar(32) DEFAULT NULL COMMENT '节点角色',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `item` varchar(255) DEFAULT NULL COMMENT '监控项',\n `param` varchar(255) DEFAULT NULL COMMENT '参数',\n `operator` varchar(255) DEFAULT NULL COMMENT '操作符',\n `value` json DEFAULT NULL COMMENT '对比值',\n `message` varchar(512) DEFAULT NULL COMMENT '消息内容',\n `notifyDuration` int(11) unsigned DEFAULT '0' COMMENT '通知间隔(单位分钟)',\n `notifiedAt` int(11) unsigned DEFAULT '0' COMMENT '上次通知时间',\n `duration` int(11) unsigned DEFAULT '0' COMMENT '时间段',\n `durationUnit` varchar(16) DEFAULT NULL COMMENT '时间段单位',\n `sumMethod` varchar(32) DEFAULT NULL COMMENT '聚合方法',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`),\n KEY `clusterId` (`clusterId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群阈值设置'",
|
||||
"definition": "CREATE TABLE `edgeNodeThresholds` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `role` varchar(32) DEFAULT NULL COMMENT '节点角色',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `item` varchar(255) DEFAULT NULL COMMENT '监控项',\n `param` varchar(255) DEFAULT NULL COMMENT '参数',\n `operator` varchar(255) DEFAULT NULL COMMENT '操作符',\n `value` json DEFAULT NULL COMMENT '对比值',\n `message` varchar(512) DEFAULT NULL COMMENT '消息内容',\n `notifyDuration` int(11) unsigned DEFAULT '0' COMMENT '通知间隔(单位分钟)',\n `notifiedAt` int(11) unsigned DEFAULT '0' COMMENT '上次通知时间',\n `duration` int(11) unsigned DEFAULT '0' COMMENT '时间段',\n `durationUnit` varchar(16) DEFAULT NULL COMMENT '时间段单位',\n `sumMethod` varchar(32) DEFAULT NULL COMMENT '聚合方法',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`),\n KEY `clusterId` (`clusterId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点监控阈值设置'",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -69345,7 +69420,7 @@
|
||||
"name": "edgeNodes",
|
||||
"engine": "InnoDB",
|
||||
"charset": "utf8mb4_general_ci",
|
||||
"definition": "CREATE TABLE `edgeNodes` (\n `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `adminId` int(11) unsigned DEFAULT '0' COMMENT '管理员ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `level` tinyint(1) unsigned DEFAULT '1' COMMENT '级别',\n `lnAddrs` json DEFAULT NULL COMMENT 'Ln级别访问地址',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续在线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续下线次数',\n `isActive` tinyint(1) unsigned DEFAULT '1' COMMENT '是否活跃',\n `inactiveNotifiedAt` bigint(11) unsigned DEFAULT '0' COMMENT '离线通知时间',\n `uniqueId` varchar(32) DEFAULT NULL COMMENT '节点ID',\n `secret` varchar(32) DEFAULT NULL COMMENT '密钥',\n `name` varchar(255) DEFAULT NULL COMMENT '节点名',\n `code` varchar(255) DEFAULT NULL COMMENT '代号',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '主集群ID',\n `secondaryClusterIds` json DEFAULT NULL COMMENT '从集群ID',\n `regionId` int(11) unsigned DEFAULT '0' COMMENT '区域ID',\n `groupId` int(11) unsigned DEFAULT '0' COMMENT '分组ID',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `status` json DEFAULT NULL COMMENT '最新的状态',\n `version` int(11) unsigned DEFAULT '0' COMMENT '当前版本号',\n `latestVersion` int(11) unsigned DEFAULT '0' COMMENT '最后版本号',\n `installDir` varchar(512) DEFAULT NULL COMMENT '安装目录',\n `isInstalled` tinyint(1) unsigned DEFAULT '0' COMMENT '是否已安装',\n `installStatus` json DEFAULT NULL COMMENT '安装状态',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n `connectedAPINodes` json DEFAULT NULL COMMENT '当前连接的API节点',\n `maxCPU` int(4) unsigned DEFAULT '0' COMMENT '可以使用的最多CPU',\n `maxThreads` int(11) unsigned DEFAULT '0' COMMENT '最大线程数',\n `ddosProtection` json DEFAULT NULL COMMENT 'DDOS配置',\n `dnsRoutes` json DEFAULT NULL COMMENT 'DNS线路设置',\n `maxCacheDiskCapacity` json DEFAULT NULL COMMENT '硬盘缓存容量',\n `maxCacheMemoryCapacity` json DEFAULT NULL COMMENT '内存缓存容量',\n `cacheDiskDir` varchar(255) DEFAULT NULL COMMENT '主缓存目录',\n `cacheDiskSubDirs` json DEFAULT NULL COMMENT '其他缓存目录',\n `dnsResolver` json DEFAULT NULL COMMENT 'DNS解析器',\n `enableIPLists` tinyint(1) unsigned DEFAULT '1' COMMENT '启用IP名单',\n `apiNodeAddrs` json DEFAULT NULL COMMENT 'API节点地址',\n PRIMARY KEY (`id`),\n KEY `uniqueId` (`uniqueId`),\n KEY `clusterId` (`clusterId`),\n KEY `groupId` (`groupId`),\n KEY `regionId` (`regionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点'",
|
||||
"definition": "CREATE TABLE `edgeNodes` (\n `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `adminId` int(11) unsigned DEFAULT '0' COMMENT '管理员ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `level` tinyint(1) unsigned DEFAULT '1' COMMENT '级别',\n `lnAddrs` json DEFAULT NULL COMMENT 'Ln级别访问地址',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续在线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续下线次数',\n `isActive` tinyint(1) unsigned DEFAULT '1' COMMENT '是否活跃',\n `inactiveNotifiedAt` bigint(11) unsigned DEFAULT '0' COMMENT '离线通知时间',\n `uniqueId` varchar(32) DEFAULT NULL COMMENT '节点ID',\n `secret` varchar(32) DEFAULT NULL COMMENT '密钥',\n `name` varchar(255) DEFAULT NULL COMMENT '节点名',\n `code` varchar(255) DEFAULT NULL COMMENT '代号',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '主集群ID',\n `secondaryClusterIds` json DEFAULT NULL COMMENT '从集群ID',\n `regionId` int(11) unsigned DEFAULT '0' COMMENT '区域ID',\n `groupId` int(11) unsigned DEFAULT '0' COMMENT '分组ID',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `status` json DEFAULT NULL COMMENT '最新的状态',\n `version` int(11) unsigned DEFAULT '0' COMMENT '当前版本号',\n `latestVersion` int(11) unsigned DEFAULT '0' COMMENT '最后版本号',\n `installDir` varchar(512) DEFAULT NULL COMMENT '安装目录',\n `isInstalled` tinyint(1) unsigned DEFAULT '0' COMMENT '是否已安装',\n `installStatus` json DEFAULT NULL COMMENT '安装状态',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n `connectedAPINodes` json DEFAULT NULL COMMENT '当前连接的API节点',\n `maxCPU` int(4) unsigned DEFAULT '0' COMMENT '可以使用的最多CPU',\n `maxThreads` int(11) unsigned DEFAULT '0' COMMENT '最大线程数',\n `ddosProtection` json DEFAULT NULL COMMENT 'DDOS配置',\n `dnsRoutes` json DEFAULT NULL COMMENT 'DNS线路设置',\n `maxCacheDiskCapacity` json DEFAULT NULL COMMENT '硬盘缓存容量',\n `maxCacheMemoryCapacity` json DEFAULT NULL COMMENT '内存缓存容量',\n `cacheDiskDir` varchar(255) DEFAULT NULL COMMENT '主缓存目录',\n `cacheDiskSubDirs` json DEFAULT NULL COMMENT '其他缓存目录',\n `dnsResolver` json DEFAULT NULL COMMENT 'DNS解析器',\n `enableIPLists` tinyint(1) unsigned DEFAULT '1' COMMENT '启用IP名单',\n `apiNodeAddrs` json DEFAULT NULL COMMENT 'API节点地址',\n `offlineDay` varchar(8) DEFAULT NULL COMMENT '下线日期YYYYMMDD',\n `offlineIsNotified` tinyint(1) unsigned DEFAULT '0' COMMENT '下线是否已通知',\n `isBackupForCluster` tinyint(1) unsigned DEFAULT '0' COMMENT '是否为集群备用节点',\n `isBackupForGroup` tinyint(1) unsigned DEFAULT '0' COMMENT '是否为分组备用节点',\n `backupIPs` json DEFAULT NULL COMMENT '备用IP',\n `actionStatus` json DEFAULT NULL COMMENT '当前动作配置',\n PRIMARY KEY (`id`),\n KEY `uniqueId` (`uniqueId`),\n KEY `clusterId` (`clusterId`),\n KEY `groupId` (`groupId`),\n KEY `regionId` (`regionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点'",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -69502,6 +69577,30 @@
|
||||
{
|
||||
"name": "apiNodeAddrs",
|
||||
"definition": "json COMMENT 'API节点地址'"
|
||||
},
|
||||
{
|
||||
"name": "offlineDay",
|
||||
"definition": "varchar(8) COMMENT '下线日期YYYYMMDD'"
|
||||
},
|
||||
{
|
||||
"name": "offlineIsNotified",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '下线是否已通知'"
|
||||
},
|
||||
{
|
||||
"name": "isBackupForCluster",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '是否为集群备用节点'"
|
||||
},
|
||||
{
|
||||
"name": "isBackupForGroup",
|
||||
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '是否为分组备用节点'"
|
||||
},
|
||||
{
|
||||
"name": "backupIPs",
|
||||
"definition": "json COMMENT '备用IP'"
|
||||
},
|
||||
{
|
||||
"name": "actionStatus",
|
||||
"definition": "json COMMENT '当前动作配置'"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
|
||||
@@ -87,8 +87,8 @@ func (this *DNSTaskExecutor) loop() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case dnsmodels.DNSTaskTypeClusterChange:
|
||||
err = this.doCluster(taskId, taskVersion, int64(task.ClusterId))
|
||||
case dnsmodels.DNSTaskTypeClusterChange, dnsmodels.DNSTaskTypeClusterNodesChange:
|
||||
err = this.doCluster(taskId, taskVersion, int64(task.ClusterId), task.Type == dnsmodels.DNSTaskTypeClusterNodesChange)
|
||||
if err != nil {
|
||||
err = dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskError(nil, taskId, err.Error())
|
||||
if err != nil {
|
||||
@@ -300,7 +300,7 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
|
||||
|
||||
// 转交给cluster统一处理
|
||||
if nodeClusterId > 0 {
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, nodeClusterId, dnsmodels.DNSTaskTypeClusterChange)
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, nodeClusterId, dnsmodels.DNSTaskTypeClusterNodesChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -310,7 +310,7 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterChange)
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterNodesChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -323,8 +323,8 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
|
||||
}
|
||||
|
||||
// 修改集群相关记录
|
||||
func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterId int64) error {
|
||||
isOk := false
|
||||
func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterId int64, nodesOnly bool) error {
|
||||
var isOk = false
|
||||
defer func() {
|
||||
if isOk {
|
||||
err := dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskDone(nil, taskId, taskVersion)
|
||||
@@ -378,6 +378,14 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
|
||||
var isChanged = false
|
||||
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
|
||||
for _, node := range nodes {
|
||||
shouldSkip, shouldOverwrite, ipAddressesStrings, err := models.SharedNodeDAO.CheckNodeIPAddresses(tx, node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if shouldSkip {
|
||||
continue
|
||||
}
|
||||
|
||||
routes, err := node.DNSRouteCodesForDomainId(domainId)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -387,26 +395,36 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
|
||||
}
|
||||
|
||||
// 所有的IP记录
|
||||
ipAddresses, err := models.SharedNodeIPAddressDAO.FindAllEnabledAddressesWithNode(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return err
|
||||
if !shouldOverwrite {
|
||||
ipAddresses, err := models.SharedNodeIPAddressDAO.FindAllEnabledAddressesWithNode(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, ipAddress := range ipAddresses {
|
||||
// 检查专属节点
|
||||
if !ipAddress.IsValidInCluster(clusterId) {
|
||||
continue
|
||||
}
|
||||
|
||||
var ip = ipAddress.DNSIP()
|
||||
if len(ip) == 0 || !ipAddress.CanAccess || !ipAddress.IsUp || !ipAddress.IsOn {
|
||||
continue
|
||||
}
|
||||
if net.ParseIP(ip) == nil {
|
||||
continue
|
||||
}
|
||||
ipAddressesStrings = append(ipAddressesStrings, ip)
|
||||
}
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
|
||||
if len(ipAddressesStrings) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, ipAddress := range ipAddresses {
|
||||
// 检查专属节点
|
||||
if !ipAddress.IsValidInCluster(clusterId) {
|
||||
continue
|
||||
}
|
||||
|
||||
var ip = ipAddress.DNSIP()
|
||||
if len(ip) == 0 || !ipAddress.CanAccess || !ipAddress.IsUp || !ipAddress.IsOn {
|
||||
continue
|
||||
}
|
||||
if net.ParseIP(ip) == nil {
|
||||
continue
|
||||
}
|
||||
for _, ip := range ipAddressesStrings {
|
||||
for _, route := range routes {
|
||||
var key = route + "@" + ip
|
||||
_, ok := oldRecordsMap[key]
|
||||
@@ -456,80 +474,82 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
|
||||
}
|
||||
|
||||
// 服务域名
|
||||
servers, err := models.SharedServerDAO.FindAllServersDNSWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverRecords := []*dnstypes.Record{} // 之所以用数组再存一遍,是因为dnsName可能会重复
|
||||
serverRecordsMap := map[string]*dnstypes.Record{} // dnsName => *Record
|
||||
for _, record := range records {
|
||||
if record.Type == dnstypes.RecordTypeCNAME && record.Value == clusterDomain+"." {
|
||||
serverRecords = append(serverRecords, record)
|
||||
serverRecordsMap[record.Name] = record
|
||||
if !nodesOnly {
|
||||
servers, err := models.SharedServerDAO.FindAllServersDNSWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的域名
|
||||
var serverDNSNames = []string{}
|
||||
for _, server := range servers {
|
||||
var dnsName = server.DnsName
|
||||
if len(dnsName) == 0 {
|
||||
continue
|
||||
}
|
||||
serverDNSNames = append(serverDNSNames, dnsName)
|
||||
_, ok := serverRecordsMap[dnsName]
|
||||
if !ok {
|
||||
isChanged = true
|
||||
err = manager.AddRecord(domain, &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: dnsName,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
serverRecords := []*dnstypes.Record{} // 之所以用数组再存一遍,是因为dnsName可能会重复
|
||||
serverRecordsMap := map[string]*dnstypes.Record{} // dnsName => *Record
|
||||
for _, record := range records {
|
||||
if record.Type == dnstypes.RecordTypeCNAME && record.Value == clusterDomain+"." {
|
||||
serverRecords = append(serverRecords, record)
|
||||
serverRecordsMap[record.Name] = record
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动设置的CNAME
|
||||
var cnameRecords = []string{}
|
||||
if dnsConfig != nil {
|
||||
cnameRecords = dnsConfig.CNAMERecords
|
||||
}
|
||||
for _, cnameRecord := range cnameRecords {
|
||||
// 如果记录已存在,则跳过
|
||||
if lists.ContainsString(serverDNSNames, cnameRecord) {
|
||||
continue
|
||||
}
|
||||
|
||||
serverDNSNames = append(serverDNSNames, cnameRecord)
|
||||
_, ok := serverRecordsMap[cnameRecord]
|
||||
if !ok {
|
||||
isChanged = true
|
||||
err = manager.AddRecord(domain, &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: cnameRecord,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
// 新增的域名
|
||||
var serverDNSNames = []string{}
|
||||
for _, server := range servers {
|
||||
var dnsName = server.DnsName
|
||||
if len(dnsName) == 0 {
|
||||
continue
|
||||
}
|
||||
serverDNSNames = append(serverDNSNames, dnsName)
|
||||
_, ok := serverRecordsMap[dnsName]
|
||||
if !ok {
|
||||
isChanged = true
|
||||
err = manager.AddRecord(domain, &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: dnsName,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 多余的域名
|
||||
for _, record := range serverRecords {
|
||||
if !lists.ContainsString(serverDNSNames, record.Name) {
|
||||
isChanged = true
|
||||
err = manager.DeleteRecord(domain, record)
|
||||
if err != nil {
|
||||
return err
|
||||
// 自动设置的CNAME
|
||||
var cnameRecords = []string{}
|
||||
if dnsConfig != nil {
|
||||
cnameRecords = dnsConfig.CNAMERecords
|
||||
}
|
||||
for _, cnameRecord := range cnameRecords {
|
||||
// 如果记录已存在,则跳过
|
||||
if lists.ContainsString(serverDNSNames, cnameRecord) {
|
||||
continue
|
||||
}
|
||||
|
||||
serverDNSNames = append(serverDNSNames, cnameRecord)
|
||||
_, ok := serverRecordsMap[cnameRecord]
|
||||
if !ok {
|
||||
isChanged = true
|
||||
err = manager.AddRecord(domain, &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: cnameRecord,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 多余的域名
|
||||
for _, record := range serverRecords {
|
||||
if !lists.ContainsString(serverDNSNames, record.Name) {
|
||||
isChanged = true
|
||||
err = manager.DeleteRecord(domain, record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !plus
|
||||
|
||||
package tasks_test
|
||||
|
||||
import (
|
||||
|
||||
@@ -127,7 +127,7 @@ func (this *HealthCheckClusterTask) Loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var message = "有" + numberutils.FormatInt(len(failedResults)) + "个节点在健康检查中出现问题"
|
||||
var message = "有" + numberutils.FormatInt(len(failedResults)) + "个节点IP在健康检查中出现问题"
|
||||
err = models.NewMessageDAO().CreateClusterMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, models.MessageTypeHealthCheckFailed, models.MessageLevelError, message, message, failedResultsJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -66,7 +67,7 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
|
||||
|
||||
var tx *dbs.Tx
|
||||
for _, node := range nodes {
|
||||
if !node.IsOn {
|
||||
if !node.IsOn || node.IsBackupForCluster || node.IsBackupForGroup || (len(node.OfflineDay) > 0 && node.OfflineDay < timeutil.Format("Ymd")) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -194,6 +195,15 @@ func (this *HealthCheckExecutor) runNode(healthCheckConfig *serverconfigs.Health
|
||||
this.logErr("HealthCheckExecutor", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 触发节点动作
|
||||
if !result.IsOk {
|
||||
err := this.fireNodeActions(int64(result.Node.Id))
|
||||
if err != nil {
|
||||
this.logErr("HealthCheckExecutor", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 触发阈值
|
||||
|
||||
9
internal/tasks/health_check_executor_ext.go
Normal file
9
internal/tasks/health_check_executor_ext.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package tasks
|
||||
|
||||
// 触发节点动作
|
||||
func (this *HealthCheckExecutor) fireNodeActions(nodeId int64) error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user