Files
waf-platform/EdgeAPI/internal/db/models/node_dao_ext_plus.go

880 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package models
import (
"encoding/json"
"errors"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
"github.com/TeaOSLab/EdgeAPI/internal/zero"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"net/http"
"strings"
"sync"
"time"
)
// 从集群加载其他服务
func (this *NodeDAO) loadServersFromCluster(tx *dbs.Tx, clusterId int64, serverIdMap map[int64]zero.Zero) ([]*Server, error) {
// 高防实例
// TODO 将来支持部署到具体节点
objectCodes, err := SharedADPackageInstanceDAO.FindAvailableObjectCodesInCluster(tx, clusterId)
if err != nil {
return nil, err
}
var resultServers = []*Server{}
for _, objectCode := range objectCodes {
objectType, objectValue := SharedUserADInstanceDAO.SplitObjectCode(objectCode)
if objectType == ADObjectTypeServer && len(objectValue) > 0 {
var serverId = types.Int64(objectValue)
if serverId > 0 {
_, ok := serverIdMap[serverId]
if !ok {
serverIdMap[serverId] = zero.Zero{}
// TODO 将来支持一次性读取一批server
server, err := SharedServerDAO.FindEnabledServer(tx, serverId)
if err != nil {
return nil, err
}
if server != nil && server.IsOn {
resultServers = append(resultServers, server)
}
}
}
}
}
return resultServers, nil
}
// 组合扩展配置
func (this *NodeDAO) composeExtConfig(tx *dbs.Tx, config *nodeconfigs.NodeConfig, clusterIds []int64, cacheMap *utils.CacheMap) error {
// 脚本
// scripts
scriptConfigs, err := SharedScriptHistoryDAO.ComposeScriptConfigs(tx, 0, cacheMap)
if err != nil {
return err
}
config.CommonScripts = scriptConfigs
// 套餐
// plan
plans, err := SharedPlanDAO.FindAllAvailableBasicPlans(tx)
if err != nil {
return err
}
var planMap = map[int64]*serverconfigs.PlanConfig{}
for _, plan := range plans {
planMap[int64(plan.Id)] = &serverconfigs.PlanConfig{
Id: int64(plan.Id),
Name: plan.Name,
BandwidthLimitPerNode: plan.DecodeBandwidthLimitPerNode(),
TrafficLimit: plan.DecodeTrafficLimit(),
MaxUploadSize: plan.DecodeMaxUploadSize(),
}
}
config.Plans = planMap
// 父节点
// 这里不需要进行 teaconst.IsPlus 判断是为了防止在API节点升级过程中或者用户授权过期又激活时节点无法正常更新
if config.Level == 1 {
parentNodes, err := SharedNodeDAO.FindParentNodeConfigs(tx, config.Id, config.GroupId, clusterIds, types.Int(config.Level))
if err != nil {
return err
}
config.ParentNodes = parentNodes
}
return nil
}
// UpdateNodeSchedule 修改智能调度信息
// offlineDay YYYYMMDD
func (this *NodeDAO) UpdateNodeSchedule(tx *dbs.Tx, nodeId int64, offlineDay string, isBackupForCluster bool, isBackupForGroup bool, backupIPs []string) error {
if nodeId <= 0 {
return errors.New("invalid nodeId")
}
var op = NewNodeOperator()
op.Id = nodeId
if len(offlineDay) > 0 && !regexputils.YYYYMMDD.MatchString(offlineDay) {
return errors.New("invalid 'offlineDay' value: " + offlineDay)
}
op.OfflineDay = offlineDay
if offlineDay >= timeutil.Format("Ymd") {
op.OfflineIsNotified = false
}
op.IsBackupForCluster = isBackupForCluster
op.IsBackupForGroup = isBackupForGroup
if backupIPs == nil {
backupIPs = []string{}
}
backupIPsJSON, err := json.Marshal(backupIPs)
if err != nil {
return err
}
op.BackupIPs = backupIPsJSON
err = this.Save(tx, op)
if err != nil {
return err
}
return this.NotifyDNSUpdate(tx, nodeId)
}
// FindAllNodeScheduleWithClusterId 查找集群下的节点
func (this *NodeDAO) FindAllNodeScheduleWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
if clusterId <= 0 {
return
}
_, err = this.Query(tx).
Result("id", "name", "groupId", "offlineDay", "backupIPs", "isBackupForCluster", "isBackupForGroup", "actionStatus").
Attr("clusterId", clusterId).
State(NodeStateEnabled).
Slice(&result).
FindAll()
return
}
// FindNodeSchedule 查找智能调度信息
func (this *NodeDAO) FindNodeSchedule(tx *dbs.Tx, nodeId int64) (node *Node, err error) {
if nodeId <= 0 {
err = errors.New("invalid nodeId")
return
}
one, err := this.Query(tx).
Result("id", "offlineDay", "isBackupForCluster", "isBackupForGroup", "backupIPs", "actionStatus").
Pk(nodeId).
Find()
if err != nil || one == nil {
return nil, err
}
return one.(*Node), nil
}
// NotifyNodesWithOfflineDay 通知租期到期的节点
var notifiedOfflineDayMap = map[string]bool{} // DAY_{END|00}
var notifiedOfflineDayLocker = &sync.Mutex{}
func (this *NodeDAO) NotifyNodesWithOfflineDay(tx *dbs.Tx) error {
// 每天最多两次
var cacheKey = timeutil.Format("Ymd")
var endHour = 23
if time.Now().Hour() == endHour {
cacheKey += "_END"
} else {
cacheKey += "_00"
}
notifiedOfflineDayLocker.Lock()
if notifiedOfflineDayMap[cacheKey] {
notifiedOfflineDayLocker.Unlock()
return nil
}
notifiedOfflineDayLocker.Unlock()
var query = this.Query(tx).
State(NodeStateEnabled).
Result("id", "clusterId", "offlineDay").
Attr("offlineIsNotified", false)
if time.Now().Hour() == endHour {
// 提前将今天到期的也下线
query.
Where("(LENGTH(offlineDay) > 0 AND offlineDay<=:offlineDay)").
Param("offlineDay", timeutil.Format("Ymd"))
} else {
// 将以往的下线
query.
Where("(LENGTH(offlineDay) > 0 AND offlineDay<:offlineDay)").
Param("offlineDay", timeutil.Format("Ymd"))
}
nodeOnes, err := query.
FindAll()
if err != nil {
return err
}
var clusterIdMap = map[int64]bool{} // clusterId => bool
for _, nodeOne := range nodeOnes {
var node = nodeOne.(*Node)
var offlineDay = node.OfflineDay
if len(offlineDay) != 8 {
continue
}
var realOfflineDay = offlineDay[:4] + "-" + offlineDay[4:6] + "-" + offlineDay[6:]
var nodeId = int64(node.Id)
var clusterId = int64(node.ClusterId)
if clusterId > 0 && !clusterIdMap[clusterId] {
err = dns.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dns.DNSTaskTypeClusterNodesChange)
if err != nil {
return err
}
clusterIdMap[clusterId] = true
}
// 设置为已通知
err = this.Query(tx).
Pk(nodeId).
Set("offlineIsNotified", true).
UpdateQuickly()
if err != nil {
return err
}
// 发送消息
err = SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, MessageTypeNodeOfflineDay, MessageLevelError, "节点租期已结束("+realOfflineDay+"", "节点租期已结束("+realOfflineDay+")", nil, true)
if err != nil {
return err
}
}
notifiedOfflineDayLocker.Lock()
notifiedOfflineDayMap[cacheKey] = true
notifiedOfflineDayLocker.Unlock()
return nil
}
// ResetNodeActionStatus 重置节点动作状态
// checkConds 是否检查条件
func (this *NodeDAO) ResetNodeActionStatus(tx *dbs.Tx, nodeId int64, checkConds bool) error {
if nodeId <= 0 {
return errors.New("invalid 'nodeId'")
}
nodeOne, err := this.Query(tx).
Pk(nodeId).
Result("clusterId", "actionStatus").
Find()
if err != nil {
return err
}
if nodeOne == nil {
return nil
}
var node = nodeOne.(*Node)
var clusterId = int64(node.ClusterId)
if clusterId <= 0 {
return nil
}
if len(node.ActionStatus) == 0 {
return nil
}
if checkConds {
var actionStatus = &nodeconfigs.NodeActionStatus{}
err = json.Unmarshal(node.ActionStatus, actionStatus)
if err != nil {
return err
}
// 处理健康检查的特殊情况
if actionStatus.ActionId > 0 {
upAddressId, err := SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddressId(tx, nodeId, true, nodeconfigs.NodeRoleNode)
if err != nil {
return err
}
if upAddressId <= 0 {
if actionStatus.DurationSeconds <= 0 || actionStatus.DurationSeconds > 3600 {
actionStatus.DurationSeconds = 3600
}
actionStatus.ExpiresAt += actionStatus.DurationSeconds
actionStatusJSON, err := json.Marshal(actionStatus)
if err != nil {
return err
}
err = this.Query(tx).
Pk(nodeId).
Set("actionStatus", actionStatusJSON).
UpdateQuickly()
if err != nil {
return err
}
// 发送通知
return SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, MessageTypeNodeSchedule, MessageLevelError, "节点未能从智能调度状态中恢复", "节点由于没有可以正常访问的IP所以未能从智能调度状态中恢复将在下次循环中再次尝试。", nil, true)
}
}
}
err = this.Query(tx).
Pk(nodeId).
Set("actionStatus", dbs.SQL("NULL")).
UpdateQuickly()
if err != nil {
return err
}
err = dns.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dns.DNSTaskTypeClusterNodesChange)
if err != nil {
return err
}
// 发送通知
return SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, MessageTypeNodeSchedule, MessageLevelSuccess, "节点已从智能调度状态中恢复", "节点已从智能调度状态中恢复。", nil, true)
}
// FindNodeIdsWithExpiredActions 查找动作状态已过期的节点ID
func (this *NodeDAO) FindNodeIdsWithExpiredActions(tx *dbs.Tx) (nodeIds []int64, err error) {
ones, err := this.Query(tx).
Result("id").
State(NodeStateEnabled).
Where("(actionStatus IS NOT NULL AND JSON_EXTRACT(actionStatus, '$.expiresAt')<:currentTime)").
Param("currentTime", time.Now().Unix()).
FindAll()
if err != nil {
return nil, err
}
for _, one := range ones {
nodeIds = append(nodeIds, int64(one.(*Node).Id))
}
return
}
// CopyNodeActionsToGroup 复制动作设置到分组
func (this *NodeDAO) CopyNodeActionsToGroup(tx *dbs.Tx, nodeId int64) error {
groupId, err := this.Query(tx).
Pk(nodeId).
Result("groupId").
FindInt64Col(0)
if err != nil {
return err
}
if groupId <= 0 {
return nil
}
const nodeRole = nodeconfigs.NodeRoleNode
actions, err := SharedNodeActionDAO.FindAllNodeActions(tx, nodeRole, nodeId)
if err != nil {
return err
}
nodeOnes, err := this.Query(tx).
ResultPk().
Attr("groupId", groupId).
Neq("id", nodeId).
State(NodeStateEnabled).
FindAll()
if err != nil {
return err
}
for _, nodeOne := range nodeOnes {
var targetNodeId = int64(nodeOne.(*Node).Id)
err = SharedNodeActionDAO.DisableAllNodeActions(tx, nodeRole, targetNodeId)
if err != nil {
return err
}
for _, action := range actions {
err = SharedNodeActionDAO.DuplicateNodeAction(tx, action, nodeRole, targetNodeId)
if err != nil {
return err
}
}
}
return nil
}
// CopyNodeActionsToCluster 复制动作设置到集群
func (this *NodeDAO) CopyNodeActionsToCluster(tx *dbs.Tx, nodeId int64) error {
clusterId, err := this.Query(tx).
Pk(nodeId).
Result("clusterId").
FindInt64Col(0)
if err != nil {
return err
}
if clusterId <= 0 {
return nil
}
const nodeRole = nodeconfigs.NodeRoleNode
actions, err := SharedNodeActionDAO.FindAllNodeActions(tx, nodeRole, nodeId)
if err != nil {
return err
}
nodeOnes, err := this.Query(tx).
ResultPk().
Attr("clusterId", clusterId).
Neq("id", nodeId).
State(NodeStateEnabled).
FindAll()
if err != nil {
return err
}
for _, nodeOne := range nodeOnes {
var targetNodeId = int64(nodeOne.(*Node).Id)
err = SharedNodeActionDAO.DisableAllNodeActions(tx, nodeRole, targetNodeId)
if err != nil {
return err
}
for _, action := range actions {
err = SharedNodeActionDAO.DuplicateNodeAction(tx, action, nodeRole, targetNodeId)
if err != nil {
return err
}
}
}
return nil
}
// FireNodeActions 触发动作
func (this *NodeDAO) FireNodeActions(tx *dbs.Tx, nodeId int64, paramCode nodeconfigs.NodeActionParam, paramValue any) error {
// 只有Plus会员才会触发
if !teaconst.IsPlus {
return nil
}
nodeOne, err := this.Query(tx).
Pk(nodeId).
Result("isBackupForCluster", "isBackupForGroup", "actionStatus", "offlineDay").
State(NodeStateEnabled).
Find()
if err != nil {
return err
}
if nodeOne == nil {
return nil
}
var node = nodeOne.(*Node)
// 备用节点不处理
if node.IsBackupForCluster || node.IsBackupForGroup {
return nil
}
// 是否已下线
if node.CheckIsOffline() {
return nil
}
// 当前节点是否已经在动作状态中
var statusJSON = node.ActionStatus
if len(statusJSON) == 0 {
return this.fireNodeActions(tx, nodeId, paramCode, paramValue)
}
var status = &nodeconfigs.NodeActionStatus{}
err = json.Unmarshal(statusJSON, status)
if err != nil {
return err
}
if status.ActionId <= 0 {
return this.fireNodeActions(tx, nodeId, paramCode, paramValue)
}
// 如果现在已经处于切换状态,则不做任何处理(使用任务来处理)
return nil
}
// 触发某个参数相关的动作
func (this *NodeDAO) fireNodeActions(tx *dbs.Tx, nodeId int64, paramCode nodeconfigs.NodeActionParam, paramValue any) error {
actions, err := SharedNodeActionDAO.FindAllAvailableNodeActionsWithParam(tx, nodeconfigs.NodeRoleNode, nodeId, paramCode)
if err != nil {
return err
}
if len(actions) == 0 {
return nil
}
for _, action := range actions {
var condsConfig = action.DecodeCondsConfig()
b, err := condsConfig.Match(func(param nodeconfigs.NodeActionParam) (value any, err error) {
if paramCode == param && paramValue != nil {
return paramValue, nil
}
switch param {
case nodeconfigs.NodeActionParamDailyTrafficOut:
var today = timeutil.Format("Ymd")
stat, err := SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, nodeId, today, today)
if err != nil {
return nil, err
}
if stat != nil {
value = stat.Bytes
} else {
value = 0
}
case nodeconfigs.NodeActionParamMonthlyTrafficOut:
var monthBegin = timeutil.Format("Ym01")
var today = timeutil.Format("Ymd")
stat, err := SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, nodeId, monthBegin, today)
if err != nil {
return nil, err
}
if stat != nil {
value = stat.Bytes
} else {
value = 0
}
case nodeconfigs.NodeActionParamBandwidthIn:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemAllTraffic)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetInt64("avgInBytes") * 8
} else {
value = 0
}
case nodeconfigs.NodeActionParamBandwidthOut:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemAllTraffic)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetInt64("avgOutBytes") * 8
} else {
value = 0
}
case nodeconfigs.NodeActionParamUDPDPSIn:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemAllTraffic)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetInt64("avgUDPInDatagrams")
} else {
value = 0
}
case nodeconfigs.NodeActionParamUDPDPSOut:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemAllTraffic)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetInt64("avgUDPOutDatagrams")
} else {
value = 0
}
case nodeconfigs.NodeActionParamCPUUsage:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemCPU)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetFloat64("usage") * 100
} else {
value = 0
}
case nodeconfigs.NodeActionParamMemoryUsage:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemMemory)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetFloat64("usage") * 100
} else {
value = 0
}
case nodeconfigs.NodeActionParamLoad:
itemValue, err := SharedNodeValueDAO.FindLatestNodeValue(tx, nodeconfigs.NodeRoleNode, nodeId, nodeconfigs.NodeValueItemLoad)
if err != nil {
return nil, err
}
if itemValue == nil {
return 0, nil
}
var mapValue = itemValue.DecodeMapValue()
if mapValue != nil {
value = mapValue.GetInt64("load5m")
} else {
value = 0
}
case nodeconfigs.NodeActionParamHealthCheckFailure:
// 不需要返回值
}
return
})
if err != nil {
return err
}
if b {
return this.runAction(tx, nodeId, int64(action.Id), condsConfig, action.DecodeAction(), action.DecodeDuration())
}
}
return nil
}
// 执行动作
func (this *NodeDAO) runAction(tx *dbs.Tx, nodeId int64, actionId int64, condsConfig *nodeconfigs.NodeActionCondsConfig, actionConfig *nodeconfigs.NodeActionConfig, duration *shared.TimeDuration) error {
if actionConfig == nil {
return errors.New("'actionConfig' should not be nil")
}
// 暂时不处理secondary clusters
clusterId, err := this.Query(tx).
Result("clusterId").
Pk(nodeId).
FindInt64Col(0)
if err != nil {
return err
}
if clusterId == 0 {
return nil
}
var status = &nodeconfigs.NodeActionStatus{
ActionId: actionId,
Conds: condsConfig,
Action: actionConfig,
CreatedAt: time.Now().Unix(),
}
if duration != nil {
var seconds = duration.Seconds()
if seconds > 0 {
status.ExpiresAt = time.Now().Unix() + seconds
status.DurationSeconds = seconds
}
}
if status.ExpiresAt <= 0 {
status.ExpiresAt = time.Now().Unix() + 3600 // 默认1个小时
}
if status.DurationSeconds <= 0 {
status.DurationSeconds = 3600
}
// 特殊情况下的过期时间
if condsConfig != nil {
var now = time.Now()
for _, cond := range condsConfig.Conds {
if cond.Param == nodeconfigs.NodeActionParamDailyTrafficOut {
// 当天结束
var expiresAt = now.Unix() - int64(now.Hour()*3600) - int64(now.Minute()*60) - int64(now.Second()) + 86400
if expiresAt > status.ExpiresAt {
status.ExpiresAt = expiresAt
}
} else if cond.Param == nodeconfigs.NodeActionParamMonthlyTrafficOut {
// 当月结束
var endDay = 32 - time.Date(now.Year(), now.Month(), 32, 0, 0, 0, 0, time.Local).Day()
var expiresAt = now.Unix() - int64(now.Hour()*3600) - int64(now.Minute()*60) - int64(now.Second()) + int64((endDay-now.Day()+1)*86400)
if expiresAt > status.ExpiresAt {
status.ExpiresAt = expiresAt
}
}
}
}
statusJSON, err := json.Marshal(status)
if err != nil {
return err
}
err = this.Query(tx).
Pk(nodeId).
Set("actionStatus", statusJSON).
UpdateQuickly()
if err != nil {
return err
}
switch actionConfig.Code {
case nodeconfigs.NodeActionCodeWebHook:
var url = maps.NewMap(actionConfig.Params).GetString("url")
if len(url) > 0 {
if strings.Contains(url, "?") {
url += "&"
} else {
url += "?"
}
url += "role=node&clusterId=" + types.String(clusterId) + "&nodeId=" + types.String(nodeId)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err
}
var httpClient = utils.SharedHttpClient(5 * time.Second)
httpResp, httpErr := httpClient.Do(req)
if httpErr == nil {
_ = httpResp.Body.Close()
}
}
default:
// 通知更新
err = dns.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dns.DNSTaskTypeClusterNodesChange)
if err != nil {
return err
}
}
// 发送消息
return SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, MessageTypeNodeSchedule, MessageLevelError, "节点已满足调度条件", "节点已满足调度条件,并执行动作:"+nodeconfigs.FindNodeActionName(actionConfig.Code), nil, true)
}
// CheckNodeIPAddresses 检查节点IP地址
func (this *NodeDAO) CheckNodeIPAddresses(tx *dbs.Tx, node *Node) (shouldSkip bool, shouldOverwrite bool, ipAddressStrings []string, err error) {
// 是否到期
if len(node.OfflineDay) > 0 && node.OfflineDay < timeutil.Format("Ymd") {
// 到期后直接跳过
shouldSkip = true
return
}
// 是否为备用
if node.IsBackupForCluster || node.IsBackupForGroup {
shouldSkip = true
return
}
// 当前状态
if len(node.ActionStatus) > 0 {
var actionStatus = node.DecodeActionStatus()
if actionStatus.ActionId > 0 && actionStatus.Action != nil {
switch actionStatus.Action.Code {
case nodeconfigs.NodeActionCodeUp:
// do nothing
return
case nodeconfigs.NodeActionCodeDown:
shouldSkip = true
return
case nodeconfigs.NodeActionCodeSwitchToBackupNodesInCluster:
if node.ClusterId <= 0 {
shouldSkip = true
return
}
addresses, addressesErr := SharedNodeIPAddressDAO.FindAllBackupNodeAccessAndUpIPAddresses(tx, int64(node.ClusterId), 0, nodeconfigs.NodeRoleNode)
if addressesErr != nil {
return false, false, nil, addressesErr
}
for _, address := range addresses {
var ip = address.DNSIP()
if !lists.ContainsString(ipAddressStrings, ip) {
ipAddressStrings = append(ipAddressStrings, ip)
}
}
if len(ipAddressStrings) > 0 {
shouldOverwrite = true
}
return
case nodeconfigs.NodeActionCodeSwitchToBackupNodesInGroup:
if node.GroupId <= 0 {
shouldSkip = true
return
}
addresses, addressesErr := SharedNodeIPAddressDAO.FindAllBackupNodeAccessAndUpIPAddresses(tx, 0, int64(node.GroupId), nodeconfigs.NodeRoleNode)
if addressesErr != nil {
return false, false, nil, addressesErr
}
for _, address := range addresses {
var ip = address.DNSIP()
if !lists.ContainsString(ipAddressStrings, ip) {
ipAddressStrings = append(ipAddressStrings, ip)
}
}
if len(ipAddressStrings) > 0 {
shouldOverwrite = true
}
return
case nodeconfigs.NodeActionCodeSwitchToBackupIP:
ipAddressStrings = node.DecodeBackupIPs()
shouldOverwrite = true
return
case nodeconfigs.NodeActionCodeEnableBackupNodesInCluster:
if node.ClusterId <= 0 {
shouldSkip = true
return
}
addresses, addressesErr := SharedNodeIPAddressDAO.FindAllBackupNodeAccessAndUpIPAddresses(tx, int64(node.ClusterId), 0, nodeconfigs.NodeRoleNode)
if addressesErr != nil {
return false, false, nil, addressesErr
}
for _, address := range addresses {
var ip = address.DNSIP()
if !lists.ContainsString(ipAddressStrings, ip) {
ipAddressStrings = append(ipAddressStrings, ip)
}
}
return
case nodeconfigs.NodeActionCodeEnableBackupNodesInGroup:
if node.GroupId <= 0 {
// 不能跳过
return
}
addresses, addressesErr := SharedNodeIPAddressDAO.FindAllBackupNodeAccessAndUpIPAddresses(tx, 0, int64(node.GroupId), nodeconfigs.NodeRoleNode)
if addressesErr != nil {
return false, false, nil, addressesErr
}
for _, address := range addresses {
var ip = address.DNSIP()
if !lists.ContainsString(ipAddressStrings, ip) {
ipAddressStrings = append(ipAddressStrings, ip)
}
}
return
case nodeconfigs.NodeActionCodeEnableBackupIP:
ipAddressStrings = node.DecodeBackupIPs()
return
case nodeconfigs.NodeActionCodeWebHook:
// do nothing
return
}
}
}
return
}