DNS节点增加在线状态通知

This commit is contained in:
GoEdgeLab
2021-08-08 10:29:48 +08:00
parent 11f7e5010e
commit 07aa0990f8
14 changed files with 623 additions and 86 deletions

View File

@@ -4,6 +4,7 @@ import (
"crypto/md5"
"fmt"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
@@ -28,8 +29,8 @@ const (
MessageTypeHealthCheckFailed MessageType = "HealthCheckFailed" // 节点健康检查失败
MessageTypeHealthCheckNodeUp MessageType = "HealthCheckNodeUp" // 因健康检查节点上线
MessageTypeHealthCheckNodeDown MessageType = "HealthCheckNodeDown" // 因健康检查节点下线
MessageTypeNodeInactive MessageType = "NodeInactive" // 节点不活跃
MessageTypeNodeActive MessageType = "NodeActive" // 节点活跃
MessageTypeNodeInactive MessageType = "NodeInactive" // 边缘节点不活跃
MessageTypeNodeActive MessageType = "NodeActive" // 边缘节点活跃
MessageTypeClusterDNSSyncFailed MessageType = "ClusterDNSSyncFailed" // DNS同步失败
MessageTypeSSLCertExpiring MessageType = "SSLCertExpiring" // SSL证书即将过期
MessageTypeSSLCertACMETaskFailed MessageType = "SSLCertACMETaskFailed" // SSL证书任务执行失败
@@ -39,6 +40,9 @@ const (
MessageTypeServerNamesAuditingFailed MessageType = "ServerNamesAuditingFailed" // 服务域名审核失败
MessageTypeThresholdSatisfied MessageType = "ThresholdSatisfied" // 满足阈值
MessageTypeFirewallEvent MessageType = "FirewallEvent" // 防火墙事件
MessageTypeNSNodeInactive MessageType = "NSNodeInactive" // 边缘节点不活跃
MessageTypeNSNodeActive MessageType = "NSNodeActive" // 边缘节点活跃
)
type MessageDAO dbs.DAO
@@ -93,8 +97,8 @@ func (this *MessageDAO) FindEnabledMessage(tx *dbs.Tx, id int64) (*Message, erro
}
// CreateClusterMessage 创建集群消息
func (this *MessageDAO) CreateClusterMessage(tx *dbs.Tx, clusterId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) error {
_, err := this.createMessage(tx, clusterId, 0, messageType, level, subject, body, paramsJSON)
func (this *MessageDAO) CreateClusterMessage(tx *dbs.Tx, role string, clusterId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) error {
_, err := this.createMessage(tx, role, clusterId, 0, messageType, level, subject, body, paramsJSON)
if err != nil {
return err
}
@@ -113,9 +117,9 @@ func (this *MessageDAO) CreateClusterMessage(tx *dbs.Tx, clusterId int64, messag
}
// CreateNodeMessage 创建节点消息
func (this *MessageDAO) CreateNodeMessage(tx *dbs.Tx, clusterId int64, nodeId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) error {
func (this *MessageDAO) CreateNodeMessage(tx *dbs.Tx, role string, clusterId int64, nodeId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) error {
// 检查N分钟内是否已经发送过
hash := this.calHash(subject, body, paramsJSON)
hash := this.calHash(role, clusterId, nodeId, subject, body, paramsJSON)
exists, err := this.Query(tx).
Attr("hash", hash).
Gt("createdAt", time.Now().Unix()-10*60). // 10分钟
@@ -127,31 +131,34 @@ func (this *MessageDAO) CreateNodeMessage(tx *dbs.Tx, clusterId int64, nodeId in
return nil
}
_, err = this.createMessage(tx, clusterId, nodeId, messageType, level, subject, body, paramsJSON)
_, err = this.createMessage(tx, role, clusterId, nodeId, messageType, level, subject, body, paramsJSON)
if err != nil {
return err
}
// 发送给媒介接收人 - 集群
err = SharedMessageTaskDAO.CreateMessageTasks(tx, MessageTaskTarget{
ClusterId: clusterId,
NodeId: 0,
ServerId: 0,
}, messageType, subject, body)
if err != nil {
return err
}
// 发送给媒介接收人 - 节点
if nodeId > 0 {
// TODO 目前只支持边缘节点发送消息将来要支持NS节点
if role == nodeconfigs.NodeRoleNode {
// 发送给媒介接收人 - 集群
err = SharedMessageTaskDAO.CreateMessageTasks(tx, MessageTaskTarget{
ClusterId: clusterId,
NodeId: nodeId,
NodeId: 0,
ServerId: 0,
}, messageType, subject, body)
if err != nil {
return err
}
// 发送给媒介接收人 - 节点
if nodeId > 0 {
err = SharedMessageTaskDAO.CreateMessageTasks(tx, MessageTaskTarget{
ClusterId: clusterId,
NodeId: nodeId,
ServerId: 0,
}, messageType, subject, body)
if err != nil {
return err
}
}
}
return nil
@@ -179,7 +186,7 @@ func (this *MessageDAO) CreateMessage(tx *dbs.Tx, adminId int64, userId int64, m
op.State = MessageStateEnabled
op.IsRead = false
op.Day = timeutil.Format("Ymd")
op.Hash = this.calHash(subject, body, paramsJSON)
op.Hash = this.calHash(nodeconfigs.NodeRoleAdmin, 0, 0, subject, body, paramsJSON)
err := this.Save(tx, op)
if err != nil {
return err
@@ -287,13 +294,14 @@ func (this *MessageDAO) CheckMessageUser(tx *dbs.Tx, messageId int64, adminId in
}
// 创建消息
func (this *MessageDAO) createMessage(tx *dbs.Tx, clusterId int64, nodeId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) (int64, error) {
func (this *MessageDAO) createMessage(tx *dbs.Tx, role string, clusterId int64, nodeId int64, messageType MessageType, level string, subject string, body string, paramsJSON []byte) (int64, error) {
// TODO 检查同样的消息最近是否发送过
// 创建新消息
op := NewMessageOperator()
op.AdminId = 0 // TODO
op.UserId = 0 // TODO
op.Role = role
op.ClusterId = clusterId
op.NodeId = nodeId
op.Type = messageType
@@ -314,7 +322,7 @@ func (this *MessageDAO) createMessage(tx *dbs.Tx, clusterId int64, nodeId int64,
op.State = MessageStateEnabled
op.CreatedAt = time.Now().Unix()
op.Day = timeutil.Format("Ymd")
op.Hash = this.calHash(subject, body, paramsJSON)
op.Hash = this.calHash(role, clusterId, nodeId, subject, body, paramsJSON)
err := this.Save(tx, op)
if err != nil {
@@ -324,10 +332,11 @@ func (this *MessageDAO) createMessage(tx *dbs.Tx, clusterId int64, nodeId int64,
}
// 计算Hash
func (this *MessageDAO) calHash(subject string, body string, paramsJSON []byte) string {
func (this *MessageDAO) calHash(role string, clusterId int64, nodeId int64, subject string, body string, paramsJSON []byte) string {
h := md5.New()
h.Write([]byte(subject))
h.Write([]byte(body))
h.Write([]byte(role + "@" + types.String(clusterId) + "@" + types.String(nodeId)))
h.Write([]byte(subject + "@"))
h.Write([]byte(body + "@"))
h.Write(paramsJSON)
return fmt.Sprintf("%x", h.Sum(nil))
}

View File

@@ -5,6 +5,7 @@ type Message struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Role string `field:"role"` // 角色
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
Level string `field:"level"` // 级别
@@ -23,6 +24,7 @@ type MessageOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
Role interface{} // 角色
ClusterId interface{} // 集群ID
NodeId interface{} // 节点ID
Level interface{} // 级别

View File

@@ -134,9 +134,9 @@ func (this *NSNodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx, clusterId int64, in
case configutils.BoolStateAll:
// 所有
case configutils.BoolStateYes:
query.Where("JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
query.Where("(isActive=1 AND JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60)")
case configutils.BoolStateNo:
query.Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
query.Where("(isActive=0 OR status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
}
if len(keyword) > 0 {
query.Where("(name LIKE :keyword)").
@@ -167,9 +167,9 @@ func (this *NSNodeDAO) ListAllEnabledNodesMatch(tx *dbs.Tx, clusterId int64, ins
case configutils.BoolStateAll:
// 所有
case configutils.BoolStateYes:
query.Where("JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
query.Where("(isActive=1 AND JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60)")
case configutils.BoolStateNo:
query.Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
query.Where("(isActive=0 OR status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
}
if clusterId > 0 {
@@ -428,6 +428,76 @@ func (this *NSNodeDAO) FindNodeClusterId(tx *dbs.Tx, nodeId int64) (int64, error
FindInt64Col(0)
}
// FindNodeActive 检查节点活跃状态
func (this *NSNodeDAO) FindNodeActive(tx *dbs.Tx, nodeId int64) (bool, error) {
isActive, err := this.Query(tx).
Pk(nodeId).
Result("isActive").
FindIntCol(0)
if err != nil {
return false, err
}
return isActive == 1, nil
}
// UpdateNodeActive 修改节点活跃状态
func (this *NSNodeDAO) UpdateNodeActive(tx *dbs.Tx, nodeId int64, isActive bool) error {
if nodeId <= 0 {
return errors.New("invalid nodeId")
}
_, err := this.Query(tx).
Pk(nodeId).
Set("isActive", isActive).
Set("statusIsNotified", false).
Update()
return err
}
// UpdateNodeConnectedAPINodes 修改当前连接的API节点
func (this *NSNodeDAO) UpdateNodeConnectedAPINodes(tx *dbs.Tx, nodeId int64, apiNodeIds []int64) error {
if nodeId <= 0 {
return errors.New("invalid nodeId")
}
op := NewNSNodeOperator()
op.Id = nodeId
if len(apiNodeIds) > 0 {
apiNodeIdsJSON, err := json.Marshal(apiNodeIds)
if err != nil {
return errors.Wrap(err)
}
op.ConnectedAPINodes = apiNodeIdsJSON
} else {
op.ConnectedAPINodes = "[]"
}
err := this.Save(tx, op)
return err
}
// FindAllNotifyingInactiveNodesWithClusterId 取得某个集群所有等待通知离线离线的节点
func (this *NSNodeDAO) FindAllNotifyingInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*NSNode, err error) {
_, err = this.Query(tx).
State(NSNodeStateEnabled).
Attr("clusterId", clusterId).
Attr("isOn", true). // 只监控启用的节点
Attr("isInstalled", true). // 只监控已经安装的节点
Attr("isActive", false). // 当前已经离线的
Attr("statusIsNotified", false).
Result("id", "name").
Slice(&result).
FindAll()
return
}
// UpdateNodeStatusIsNotified 设置状态已经通知
func (this *NSNodeDAO) UpdateNodeStatusIsNotified(tx *dbs.Tx, nodeId int64) error {
return this.Query(tx).
Pk(nodeId).
Set("statusIsNotified", true).
UpdateQuickly()
}
// NotifyUpdate 通知更新
func (this *NSNodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
// TODO 先什么都不做

View File

@@ -2,35 +2,41 @@ package nameservers
// NSNode 域名服务器节点
type NSNode struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
ClusterId uint32 `field:"clusterId"` // 集群ID
Name string `field:"name"` // 节点名称
IsOn uint8 `field:"isOn"` // 是否启用
Status string `field:"status"` // 运行状态
UniqueId string `field:"uniqueId"` // 节点ID
Secret string `field:"secret"` // 密钥
IsUp uint8 `field:"isUp"` // 是否运行
IsInstalled uint8 `field:"isInstalled"` // 是否已安装
InstallStatus string `field:"installStatus"` // 安装状态
InstallDir string `field:"installDir"` // 安装目录
State uint8 `field:"state"` // 状态
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
ClusterId uint32 `field:"clusterId"` // 集群ID
Name string `field:"name"` // 节点名称
IsOn uint8 `field:"isOn"` // 是否启用
Status string `field:"status"` // 运行状态
UniqueId string `field:"uniqueId"` // 节点ID
Secret string `field:"secret"` // 密钥
IsUp uint8 `field:"isUp"` // 是否运行
IsInstalled uint8 `field:"isInstalled"` // 是否已安装
InstallStatus string `field:"installStatus"` // 安装状态
InstallDir string `field:"installDir"` // 安装目录
State uint8 `field:"state"` // 状态
IsActive uint8 `field:"isActive"` // 是否活跃
StatusIsNotified uint8 `field:"statusIsNotified"` // 活跃状态已经通知
ConnectedAPINodes string `field:"connectedAPINodes"` // 当前连接的API节点
}
type NSNodeOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
ClusterId interface{} // 集群ID
Name interface{} // 节点名称
IsOn interface{} // 是否启用
Status interface{} // 运行状态
UniqueId interface{} // 节点ID
Secret interface{} // 密钥
IsUp interface{} // 是否运行
IsInstalled interface{} // 是否已安装
InstallStatus interface{} // 安装状态
InstallDir interface{} // 安装目录
State interface{} // 状态
Id interface{} // ID
AdminId interface{} // 管理员ID
ClusterId interface{} // 集群ID
Name interface{} // 节点名称
IsOn interface{} // 是否启用
Status interface{} // 运行状态
UniqueId interface{} // 节点ID
Secret interface{} // 密钥
IsUp interface{} // 是否运行
IsInstalled interface{} // 是否已安装
InstallStatus interface{} // 安装状态
InstallDir interface{} // 安装目录
State interface{} // 状态
IsActive interface{} // 是否活跃
StatusIsNotified interface{} // 活跃状态已经通知
ConnectedAPINodes interface{} // 当前连接的API节点
}
func NewNSNodeOperator() *NSNodeOperator {

View File

@@ -252,7 +252,7 @@ func (this *NodeThresholdDAO) FireNodeThreshold(tx *dbs.Tx, role string, nodeId
body = strings.Replace(body, "${item.name}", itemName, -1)
body = strings.Replace(body, "${value}", fmt.Sprintf("%.2f", paramValue), -1)
}
err = SharedMessageDAO.CreateNodeMessage(tx, clusterId, nodeId, MessageTypeThresholdSatisfied, MessageLevelWarning, subject, body, maps.Map{}.AsJSON())
err = SharedMessageDAO.CreateNodeMessage(tx, role, clusterId, nodeId, MessageTypeThresholdSatisfied, MessageLevelWarning, subject, body, maps.Map{}.AsJSON())
if err != nil {
return err
}