Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b81ffd074 | ||
|
|
eff3c77551 | ||
|
|
2089bac52f | ||
|
|
67760a53ba | ||
|
|
d4d7b1fff7 | ||
|
|
d121bc86a0 | ||
|
|
7a1bd29f6f | ||
|
|
f1af151080 | ||
|
|
f39d106bef | ||
|
|
d9c092cd31 | ||
|
|
7d1d138e42 | ||
|
|
89bd70819f | ||
|
|
15156b68e3 | ||
|
|
92a3b8f375 | ||
|
|
6a152b7775 | ||
|
|
ea915582c1 | ||
|
|
51b938b9c7 | ||
|
|
c2f559d48e | ||
|
|
a96c1434b6 | ||
|
|
d135442a52 | ||
|
|
0b8501a724 | ||
|
|
7fcc2b7dba | ||
|
|
1ea7fe0213 | ||
|
|
838d33648f | ||
|
|
6cf4a8ea3e | ||
|
|
15c40d6c96 |
@@ -9,28 +9,32 @@ import (
|
||||
)
|
||||
|
||||
type DNSProvider struct {
|
||||
raw dnsclients.ProviderInterface
|
||||
raw dnsclients.ProviderInterface
|
||||
dnsDomain string
|
||||
}
|
||||
|
||||
func NewDNSProvider(raw dnsclients.ProviderInterface) *DNSProvider {
|
||||
return &DNSProvider{raw: raw}
|
||||
func NewDNSProvider(raw dnsclients.ProviderInterface, dnsDomain string) *DNSProvider {
|
||||
return &DNSProvider{
|
||||
raw: raw,
|
||||
dnsDomain: dnsDomain,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
// 设置记录
|
||||
index := strings.Index(fqdn, "."+domain)
|
||||
index := strings.Index(fqdn, "."+this.dnsDomain)
|
||||
if index < 0 {
|
||||
return errors.New("invalid fqdn value")
|
||||
}
|
||||
recordName := fqdn[:index]
|
||||
record, err := this.raw.QueryRecord(domain, recordName, dnstypes.RecordTypeTXT)
|
||||
record, err := this.raw.QueryRecord(this.dnsDomain, recordName, dnstypes.RecordTypeTXT)
|
||||
if err != nil {
|
||||
return errors.New("query DNS record failed: " + err.Error())
|
||||
}
|
||||
if record == nil {
|
||||
err = this.raw.AddRecord(domain, &dnstypes.Record{
|
||||
err = this.raw.AddRecord(this.dnsDomain, &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: recordName,
|
||||
Type: dnstypes.RecordTypeTXT,
|
||||
@@ -41,7 +45,7 @@ func (this *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
return errors.New("create DNS record failed: " + err.Error())
|
||||
}
|
||||
} else {
|
||||
err = this.raw.UpdateRecord(domain, record, &dnstypes.Record{
|
||||
err = this.raw.UpdateRecord(this.dnsDomain, record, &dnstypes.Record{
|
||||
Name: recordName,
|
||||
Type: dnstypes.RecordTypeTXT,
|
||||
Value: value,
|
||||
|
||||
@@ -92,7 +92,7 @@ func (this *Request) runDNS() (certData []byte, keyData []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
err = client.Challenge.SetDNS01Provider(NewDNSProvider(this.task.DNSProvider))
|
||||
err = client.Challenge.SetDNS01Provider(NewDNSProvider(this.task.DNSProvider, this.task.DNSDomain))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestRequest_Run_DNS(t *testing.T) {
|
||||
AuthType: AuthTypeDNS,
|
||||
DNSProvider: dnsProvider,
|
||||
DNSDomain: "yun4s.cn",
|
||||
Domains: []string{"yun4s.cn"},
|
||||
Domains: []string{"www.yun4s.cn"},
|
||||
})
|
||||
certData, keyData, err := req.Run()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.3.0"
|
||||
Version = "0.3.1"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,9 +18,10 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.3.0"
|
||||
NodeVersion = "0.3.1"
|
||||
UserNodeVersion = "0.0.10"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.0"
|
||||
ReportNodeVersion = "0.1.0"
|
||||
)
|
||||
|
||||
@@ -94,8 +94,12 @@ func (this *DNSTaskDAO) FindAllDoingTasks(tx *dbs.Tx) (result []*DNSTask, err er
|
||||
}
|
||||
|
||||
// FindAllDoingOrErrorTasks 查找正在执行的和错误的任务
|
||||
func (this *DNSTaskDAO) FindAllDoingOrErrorTasks(tx *dbs.Tx) (result []*DNSTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *DNSTaskDAO) FindAllDoingOrErrorTasks(tx *dbs.Tx, nodeClusterId int64) (result []*DNSTask, err error) {
|
||||
var query = this.Query(tx)
|
||||
if nodeClusterId > 0 {
|
||||
query.Attr("clusterId", nodeClusterId)
|
||||
}
|
||||
_, err = query.
|
||||
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
|
||||
@@ -287,7 +287,7 @@ func (this *HTTPLocationDAO) FindEnabledLocationIdWithWebId(tx *dbs.Tx, webId in
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindEnabledLocationIdWithReverseProxyId 查找包含某个反向代理的Server
|
||||
// FindEnabledLocationIdWithReverseProxyId 查找包含某个反向代理的路由规则
|
||||
func (this *HTTPLocationDAO) FindEnabledLocationIdWithReverseProxyId(tx *dbs.Tx, reverseProxyId int64) (serverId int64, err error) {
|
||||
return this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
|
||||
@@ -48,6 +48,7 @@ const (
|
||||
|
||||
MessageTypeReportNodeInactive MessageType = "ReportNodeInactive" // 区域监控节点节点不活跃
|
||||
MessageTypeReportNodeActive MessageType = "ReportNodeActive" // 区域监控节点活跃
|
||||
MessageTypeConnectivity MessageType = "Connectivity"
|
||||
)
|
||||
|
||||
type MessageDAO dbs.DAO
|
||||
@@ -118,21 +119,23 @@ func (this *MessageDAO) CreateClusterMessage(tx *dbs.Tx, role string, clusterId
|
||||
}
|
||||
|
||||
// CreateNodeMessage 创建节点消息
|
||||
func (this *MessageDAO) CreateNodeMessage(tx *dbs.Tx, role string, 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, force bool) error {
|
||||
// 检查N分钟内是否已经发送过
|
||||
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分钟
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return nil
|
||||
if !force {
|
||||
exists, err := this.Query(tx).
|
||||
Attr("hash", hash).
|
||||
Gt("createdAt", time.Now().Unix()-10*60). // 10分钟
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.createMessage(tx, role, clusterId, nodeId, messageType, level, subject, body, paramsJSON)
|
||||
_, err := this.createMessage(tx, role, clusterId, nodeId, messageType, level, subject, body, paramsJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@ import (
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewMetricStatDAO_InsertMany(t *testing.T) {
|
||||
for i := 0; i <= 10_000_000; i++ {
|
||||
err := NewMetricStatDAO().CreateStat(nil, types.String(i)+"_v1", 18, int64(rands.Int(0, 10000)), int64(rands.Int(0, 10000)), int64(rands.Int(0, 100)), []string{"/html" + types.String(i)}, 1, "20210830", 0)
|
||||
err := NewMetricStatDAO().CreateStat(nil, types.String(i)+"_v1", 18, int64(rands.Int(0, 10000)), int64(rands.Int(0, 10000)), int64(rands.Int(0, 100)), []string{"/html" + types.String(i)}, 1, timeutil.Format("Ymd"), 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -141,6 +141,8 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: true,
|
||||
ServersAutoSync: true,
|
||||
CNameRecords: []string{},
|
||||
TTL: 0,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
if err != nil {
|
||||
@@ -436,7 +438,7 @@ func (this *NodeClusterDAO) ExistClusterDNSName(tx *dbs.Tx, dnsName string, excl
|
||||
}
|
||||
|
||||
// UpdateClusterDNS 修改集群DNS相关信息
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool) error {
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool, cnameRecords []string, ttl int32) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -445,9 +447,15 @@ func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsNam
|
||||
op.DnsName = dnsName
|
||||
op.DnsDomainId = dnsDomainId
|
||||
|
||||
if len(cnameRecords) == 0 {
|
||||
cnameRecords = []string{}
|
||||
}
|
||||
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: nodesAutoSync,
|
||||
ServersAutoSync: serversAutoSync,
|
||||
CNameRecords: cnameRecords,
|
||||
TTL: ttl,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
if err != nil {
|
||||
@@ -792,6 +800,17 @@ func (this *NodeClusterDAO) FindEnabledNodeClustersWithIds(tx *dbs.Tx, clusterId
|
||||
return
|
||||
}
|
||||
|
||||
// ExistsEnabledCluster 检查集群是否存在
|
||||
func (this *NodeClusterDAO) ExistsEnabledCluster(tx *dbs.Tx, clusterId int64) (bool, error) {
|
||||
if clusterId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
)
|
||||
|
||||
// 解析DNS配置
|
||||
// DecodeDNSConfig 解析DNS配置
|
||||
func (this *NodeCluster) DecodeDNSConfig() (*dnsconfigs.ClusterDNSConfig, error) {
|
||||
if len(this.Dns) == 0 || this.Dns == "null" {
|
||||
// 一定要返回一个默认的值,防止产生nil
|
||||
|
||||
@@ -113,7 +113,7 @@ func (this *NodeDAO) FindEnabledBasicNode(tx *dbs.Tx, nodeId int64) (*Node, erro
|
||||
one, err := this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Pk(nodeId).
|
||||
Result("id", "name", "clusterId", "isOn", "isUp").
|
||||
Result("id", "name", "clusterId", "groupId", "isOn", "isUp").
|
||||
Find()
|
||||
if one == nil {
|
||||
return nil, err
|
||||
@@ -190,7 +190,7 @@ func (this *NodeDAO) CreateNode(tx *dbs.Tx, adminId int64, name string, clusterI
|
||||
}
|
||||
|
||||
// UpdateNode 修改节点
|
||||
func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId int64, secondaryClusterIds []int64, groupId int64, regionId int64, maxCPU int32, isOn bool, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte) error {
|
||||
func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId int64, secondaryClusterIds []int64, groupId int64, regionId int64, isOn bool) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
@@ -226,14 +226,7 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
|
||||
op.GroupId = groupId
|
||||
op.RegionId = regionId
|
||||
op.LatestVersion = dbs.SQL("latestVersion+1")
|
||||
op.MaxCPU = maxCPU
|
||||
op.IsOn = isOn
|
||||
if len(maxCacheDiskCapacityJSON) > 0 {
|
||||
op.MaxCacheDiskCapacity = maxCacheDiskCapacityJSON
|
||||
}
|
||||
if len(maxCacheMemoryCapacityJSON) > 0 {
|
||||
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
||||
}
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -500,9 +493,9 @@ func (this *NodeDAO) FindAllInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int
|
||||
_, err = this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("isOn", true). // 只监控启用的节点
|
||||
Attr("isOn", true). // 只监控启用的节点
|
||||
Attr("isInstalled", true). // 只监控已经安装的节点
|
||||
Attr("isActive", true). // 当前已经在线的
|
||||
Attr("isActive", true). // 当前已经在线的
|
||||
Where("(status IS NULL OR (JSON_EXTRACT(status, '$.isActive')=false AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>10) OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>120)").
|
||||
Result("id", "name").
|
||||
Slice(&result).
|
||||
@@ -1113,6 +1106,41 @@ func (this *NodeDAO) UpdateNodeDNS(tx *dbs.Tx, nodeId int64, routes map[int64][]
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateNodeSystem 设置系统信息
|
||||
func (this *NodeDAO) UpdateNodeSystem(tx *dbs.Tx, nodeId int64, maxCPU int32) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
var op = NewNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.MaxCPU = maxCPU
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, nodeId)
|
||||
}
|
||||
|
||||
// UpdateNodeCache 设置缓存相关
|
||||
func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
var op = NewNodeOperator()
|
||||
op.Id = nodeId
|
||||
if len(maxCacheDiskCapacityJSON) > 0 {
|
||||
op.MaxCacheDiskCapacity = maxCacheDiskCapacityJSON
|
||||
}
|
||||
if len(maxCacheMemoryCapacityJSON) > 0 {
|
||||
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
||||
}
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, nodeId)
|
||||
}
|
||||
|
||||
// UpdateNodeUpCount 计算节点上线|下线状态
|
||||
func (this *NodeDAO) UpdateNodeUpCount(tx *dbs.Tx, nodeId int64, isUp bool, maxUp int, maxDown int) (changed bool, err error) {
|
||||
if nodeId <= 0 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
@@ -102,7 +103,7 @@ func (this *NodeIPAddressDAO) FindAddressName(tx *dbs.Tx, id int64) (string, err
|
||||
}
|
||||
|
||||
// CreateAddress 创建IP地址
|
||||
func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId int64, role nodeconfigs.NodeRole, name string, ip string, canAccess bool, thresholdsJSON []byte) (addressId int64, err error) {
|
||||
func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId int64, role nodeconfigs.NodeRole, name string, ip string, canAccess bool, isUp bool) (addressId int64, err error) {
|
||||
if len(role) == 0 {
|
||||
role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
@@ -113,12 +114,7 @@ func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId in
|
||||
op.Name = name
|
||||
op.Ip = ip
|
||||
op.CanAccess = canAccess
|
||||
|
||||
if len(thresholdsJSON) > 0 {
|
||||
op.Thresholds = thresholdsJSON
|
||||
} else {
|
||||
op.Thresholds = "[]"
|
||||
}
|
||||
op.IsUp = isUp
|
||||
|
||||
op.State = NodeIPAddressStateEnabled
|
||||
addressId, err = this.SaveInt64(tx, op)
|
||||
@@ -141,7 +137,7 @@ func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId in
|
||||
}
|
||||
|
||||
// UpdateAddress 修改IP地址
|
||||
func (this *NodeIPAddressDAO) UpdateAddress(tx *dbs.Tx, adminId int64, addressId int64, name string, ip string, canAccess bool, isOn bool, thresholdsJSON []byte) (err error) {
|
||||
func (this *NodeIPAddressDAO) UpdateAddress(tx *dbs.Tx, adminId int64, addressId int64, name string, ip string, canAccess bool, isOn bool, isUp bool) (err error) {
|
||||
if addressId <= 0 {
|
||||
return errors.New("invalid addressId")
|
||||
}
|
||||
@@ -152,12 +148,7 @@ func (this *NodeIPAddressDAO) UpdateAddress(tx *dbs.Tx, adminId int64, addressId
|
||||
op.Ip = ip
|
||||
op.CanAccess = canAccess
|
||||
op.IsOn = isOn
|
||||
|
||||
if len(thresholdsJSON) > 0 {
|
||||
op.Thresholds = thresholdsJSON
|
||||
} else {
|
||||
op.Thresholds = "[]"
|
||||
}
|
||||
op.IsUp = isUp
|
||||
|
||||
op.State = NodeIPAddressStateEnabled // 恢复状态
|
||||
err = this.Save(tx, op)
|
||||
@@ -234,6 +225,8 @@ func (this *NodeIPAddressDAO) FindFirstNodeAccessIPAddress(tx *dbs.Tx, nodeId in
|
||||
Attr("role", role).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("canAccess", true).
|
||||
Attr("isOn", true).
|
||||
Attr("isUp", true).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Result("ip").
|
||||
@@ -250,6 +243,8 @@ func (this *NodeIPAddressDAO) FindFirstNodeAccessIPAddressId(tx *dbs.Tx, nodeId
|
||||
Attr("role", role).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("canAccess", true).
|
||||
Attr("isOn", true).
|
||||
Attr("isUp", true).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Result("id").
|
||||
@@ -346,12 +341,13 @@ func (this *NodeIPAddressDAO) ListEnabledIPAddresses(tx *dbs.Tx, role string, no
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllEnabledAndOnIPAddressesWithClusterId 列出所有的正在启用的IP地址
|
||||
func (this *NodeIPAddressDAO) FindAllEnabledAndOnIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64) (result []*NodeIPAddress, err error) {
|
||||
// FindAllAccessibleIPAddressesWithClusterId 列出所有的正在启用的IP地址
|
||||
func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64) (result []*NodeIPAddress, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("role", role).
|
||||
Attr("isOn", true).
|
||||
Attr("canAccess", true).
|
||||
Where("nodeId IN (SELECT id FROM "+SharedNodeDAO.Table+" WHERE state=1 AND clusterId=:clusterId)").
|
||||
Param("clusterId", clusterId).
|
||||
Slice(&result).
|
||||
@@ -359,6 +355,74 @@ func (this *NodeIPAddressDAO) FindAllEnabledAndOnIPAddressesWithClusterId(tx *db
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllAccessibleIPAddressesWithClusterId 计算集群中的可用IP地址数量
|
||||
func (this *NodeIPAddressDAO) CountAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64) (count int64, err error) {
|
||||
return this.Query(tx).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("role", role).
|
||||
Attr("isOn", true).
|
||||
Attr("canAccess", true).
|
||||
Where("nodeId IN (SELECT id FROM "+SharedNodeDAO.Table+" WHERE state=1 AND clusterId=:clusterId)").
|
||||
Param("clusterId", clusterId).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListAccessibleIPAddressesWithClusterId 列出单页集群中的可用IP地址
|
||||
func (this *NodeIPAddressDAO) ListAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64, offset int64, size int64) (result []*NodeIPAddress, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("role", role).
|
||||
Attr("isOn", true).
|
||||
Attr("canAccess", true).
|
||||
Where("nodeId IN (SELECT id FROM "+SharedNodeDAO.Table+" WHERE state=1 AND clusterId=:clusterId)").
|
||||
Param("clusterId", clusterId).
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAddressConnectivity 设置连通性数据
|
||||
func (this *NodeIPAddressDAO) UpdateAddressConnectivity(tx *dbs.Tx, addrId int64, connectivity *nodeconfigs.Connectivity) error {
|
||||
connectivityJSON, err := json.Marshal(connectivity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(addrId).
|
||||
Set("connectivity", connectivityJSON).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// UpdateAddressIsUp 设置IP地址在线状态
|
||||
func (this *NodeIPAddressDAO) UpdateAddressIsUp(tx *dbs.Tx, addressId int64, isUp bool) error {
|
||||
var err = this.Query(tx).
|
||||
Pk(addressId).
|
||||
Set("isUp", isUp).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, addressId)
|
||||
}
|
||||
|
||||
// UpdateAddressBackupIP 设置备用IP
|
||||
func (this *NodeIPAddressDAO) UpdateAddressBackupIP(tx *dbs.Tx, addressId int64, thresholdId int64, ip string) error {
|
||||
if addressId <= 0 {
|
||||
return errors.New("invalid addressId")
|
||||
}
|
||||
var op = NewNodeIPAddressOperator()
|
||||
op.Id = addressId
|
||||
op.BackupThresholdId = thresholdId
|
||||
op.BackupIP = ip
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, addressId)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeIPAddressDAO) NotifyUpdate(tx *dbs.Tx, addressId int64) error {
|
||||
address, err := this.Query(tx).
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
//go:build plus
|
||||
// +build plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNodeIPAddressDAO_FireThresholds(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var nodeId int64 = 126
|
||||
node, err := SharedNodeDAO.FindEnabledNode(tx, nodeId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if node == nil {
|
||||
t.Log("node not found")
|
||||
return
|
||||
}
|
||||
err = SharedNodeIPAddressDAO.FireThresholds(tx, nodeconfigs.NodeRoleNode, nodeId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestNodeIPAddressDAO_LoopTasks(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedNodeIPAddressDAO.loopTask(tx, nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func (this *NodeIPAddressLogDAO) CreateLog(tx *dbs.Tx, adminId int64, addrId int
|
||||
op.CanAccess = addr.CanAccess
|
||||
op.IsOn = addr.IsOn
|
||||
op.IsUp = addr.IsUp
|
||||
op.BackupIP = addr.BackupIP
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNodeIPAddressDAO_FindFirstNodeAccessIPAddress(t *testing.T) {
|
||||
var dao = NewNodeIPAddressDAO()
|
||||
t.Log(dao.FindFirstNodeAccessIPAddress(nil, 48, nodeconfigs.NodeRoleNode))
|
||||
t.Log(dao.FindFirstNodeAccessIPAddressId(nil, 48, nodeconfigs.NodeRoleNode))
|
||||
}
|
||||
@@ -11,6 +11,7 @@ type NodeIPAddressLog struct {
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
CanAccess uint8 `field:"canAccess"` // 是否可访问
|
||||
Day string `field:"day"` // YYYYMMDD,用来清理
|
||||
BackupIP string `field:"backupIP"` // 备用IP
|
||||
}
|
||||
|
||||
type NodeIPAddressLogOperator struct {
|
||||
@@ -23,6 +24,7 @@ type NodeIPAddressLogOperator struct {
|
||||
IsOn interface{} // 是否启用
|
||||
CanAccess interface{} // 是否可访问
|
||||
Day interface{} // YYYYMMDD,用来清理
|
||||
BackupIP interface{} // 备用IP
|
||||
}
|
||||
|
||||
func NewNodeIPAddressLogOperator() *NodeIPAddressLogOperator {
|
||||
|
||||
@@ -2,33 +2,39 @@ package models
|
||||
|
||||
// NodeIPAddress 节点IP地址
|
||||
type NodeIPAddress struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Role string `field:"role"` // 节点角色
|
||||
Name string `field:"name"` // 名称
|
||||
Ip string `field:"ip"` // IP地址
|
||||
Description string `field:"description"` // 描述
|
||||
State uint8 `field:"state"` // 状态
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CanAccess uint8 `field:"canAccess"` // 是否可以访问
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsUp uint8 `field:"isUp"` // 是否上线
|
||||
Thresholds string `field:"thresholds"` // 上线阈值
|
||||
Id uint32 `field:"id"` // ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Role string `field:"role"` // 节点角色
|
||||
Name string `field:"name"` // 名称
|
||||
Ip string `field:"ip"` // IP地址
|
||||
Description string `field:"description"` // 描述
|
||||
State uint8 `field:"state"` // 状态
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CanAccess uint8 `field:"canAccess"` // 是否可以访问
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsUp uint8 `field:"isUp"` // 是否上线
|
||||
Thresholds string `field:"thresholds"` // 上线阈值
|
||||
Connectivity string `field:"connectivity"` // 连通性状态
|
||||
BackupIP string `field:"backupIP"` // 备用IP
|
||||
BackupThresholdId uint32 `field:"backupThresholdId"` // 触发备用IP的阈值
|
||||
}
|
||||
|
||||
type NodeIPAddressOperator struct {
|
||||
Id interface{} // ID
|
||||
NodeId interface{} // 节点ID
|
||||
Role interface{} // 节点角色
|
||||
Name interface{} // 名称
|
||||
Ip interface{} // IP地址
|
||||
Description interface{} // 描述
|
||||
State interface{} // 状态
|
||||
Order interface{} // 排序
|
||||
CanAccess interface{} // 是否可以访问
|
||||
IsOn interface{} // 是否启用
|
||||
IsUp interface{} // 是否上线
|
||||
Thresholds interface{} // 上线阈值
|
||||
Id interface{} // ID
|
||||
NodeId interface{} // 节点ID
|
||||
Role interface{} // 节点角色
|
||||
Name interface{} // 名称
|
||||
Ip interface{} // IP地址
|
||||
Description interface{} // 描述
|
||||
State interface{} // 状态
|
||||
Order interface{} // 排序
|
||||
CanAccess interface{} // 是否可以访问
|
||||
IsOn interface{} // 是否启用
|
||||
IsUp interface{} // 是否上线
|
||||
Thresholds interface{} // 上线阈值
|
||||
Connectivity interface{} // 连通性状态
|
||||
BackupIP interface{} // 备用IP
|
||||
BackupThresholdId interface{} // 触发备用IP的阈值
|
||||
}
|
||||
|
||||
func NewNodeIPAddressOperator() *NodeIPAddressOperator {
|
||||
|
||||
@@ -2,19 +2,43 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
func (this *NodeIPAddress) DecodeThresholds() []*nodeconfigs.NodeValueThresholdConfig {
|
||||
var result = []*nodeconfigs.NodeValueThresholdConfig{}
|
||||
if len(this.Thresholds) == 0 {
|
||||
return result
|
||||
// DecodeConnectivity 解析联通数值
|
||||
func (this *NodeIPAddress) DecodeConnectivity() *nodeconfigs.Connectivity {
|
||||
var connectivity = &nodeconfigs.Connectivity{}
|
||||
if len(this.Connectivity) > 0 {
|
||||
err := json.Unmarshal([]byte(this.Connectivity), connectivity)
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeIPAddress.DecodeConnectivity", "decode failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
err := json.Unmarshal([]byte(this.Thresholds), &result)
|
||||
if err != nil {
|
||||
// 不处理错误
|
||||
logs.Error(err)
|
||||
}
|
||||
return result
|
||||
return connectivity
|
||||
}
|
||||
|
||||
// DNSIP 获取当前DNS可以使用的IP
|
||||
func (this *NodeIPAddress) DNSIP() string {
|
||||
var backupIP = this.DecodeBackupIP()
|
||||
if len(backupIP) > 0 {
|
||||
return backupIP
|
||||
}
|
||||
return this.Ip
|
||||
}
|
||||
|
||||
// DecodeBackupIP 获取备用IP
|
||||
func (this *NodeIPAddress) DecodeBackupIP() string {
|
||||
if this.BackupThresholdId > 0 && len(this.BackupIP) > 0 {
|
||||
// 阈值是否存在
|
||||
b, err := SharedNodeIPAddressThresholdDAO.ExistsEnabledThreshold(nil, int64(this.BackupThresholdId))
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeIPAddress.DNSIP", "check enabled threshold failed: "+err.Error())
|
||||
} else {
|
||||
if b {
|
||||
return this.BackupIP
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
252
internal/db/models/node_ip_address_threshold_dao.go
Normal file
252
internal/db/models/node_ip_address_threshold_dao.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
NodeIPAddressThresholdStateEnabled = 1 // 已启用
|
||||
NodeIPAddressThresholdStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NodeIPAddressThresholdDAO dbs.DAO
|
||||
|
||||
func NewNodeIPAddressThresholdDAO() *NodeIPAddressThresholdDAO {
|
||||
return dbs.NewDAO(&NodeIPAddressThresholdDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNodeIPAddressThresholds",
|
||||
Model: new(NodeIPAddressThreshold),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NodeIPAddressThresholdDAO)
|
||||
}
|
||||
|
||||
var SharedNodeIPAddressThresholdDAO *NodeIPAddressThresholdDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNodeIPAddressThresholdDAO = NewNodeIPAddressThresholdDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNodeIPAddressThreshold 启用条目
|
||||
func (this *NodeIPAddressThresholdDAO) EnableNodeIPAddressThreshold(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodeIPAddressThresholdStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNodeIPAddressThreshold 禁用条目
|
||||
func (this *NodeIPAddressThresholdDAO) DisableNodeIPAddressThreshold(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodeIPAddressThresholdStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNodeIPAddressThreshold 查找启用中的条目
|
||||
func (this *NodeIPAddressThresholdDAO) FindEnabledNodeIPAddressThreshold(tx *dbs.Tx, id uint64) (*NodeIPAddressThreshold, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NodeIPAddressThresholdStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NodeIPAddressThreshold), err
|
||||
}
|
||||
|
||||
// FindAllEnabledThresholdsWithAddrId 查找所有阈值
|
||||
func (this *NodeIPAddressThresholdDAO) FindAllEnabledThresholdsWithAddrId(tx *dbs.Tx, addrId int64) (result []*NodeIPAddressThreshold, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("addressId", addrId).
|
||||
State(NodeIPAddressThresholdStateEnabled).
|
||||
AscPk().
|
||||
Desc("order").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 过滤参数
|
||||
for _, threshold := range result {
|
||||
err := this.formatThreshold(tx, threshold)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllEnabledThresholdsWithAddrId 计算所有阈值数量
|
||||
func (this *NodeIPAddressThresholdDAO) CountAllEnabledThresholdsWithAddrId(tx *dbs.Tx, addrId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("addressId", addrId).
|
||||
State(NodeIPAddressThresholdStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// FindThresholdNotifiedAt 查找上次通知时间
|
||||
func (this *NodeIPAddressThresholdDAO) FindThresholdNotifiedAt(tx *dbs.Tx, thresholdId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Pk(thresholdId).
|
||||
Result("notifiedAt").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// UpdateThresholdNotifiedAt 设置上次通知时间
|
||||
func (this *NodeIPAddressThresholdDAO) UpdateThresholdNotifiedAt(tx *dbs.Tx, thresholdId int64, timestamp int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(thresholdId).
|
||||
Set("notifiedAt", timestamp).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CreateThreshold 创建阈值
|
||||
func (this *NodeIPAddressThresholdDAO) CreateThreshold(tx *dbs.Tx, addressId int64, items []*nodeconfigs.IPAddressThresholdItemConfig, actions []*nodeconfigs.IPAddressThresholdActionConfig, order int) (int64, error) {
|
||||
if addressId <= 0 {
|
||||
return 0, errors.New("invalid addressId")
|
||||
}
|
||||
var op = NewNodeIPAddressThresholdOperator()
|
||||
op.Order = order
|
||||
op.AddressId = addressId
|
||||
|
||||
if len(items) > 0 {
|
||||
itemsJSON, err := json.Marshal(items)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Items = itemsJSON
|
||||
} else {
|
||||
op.Items = "[]"
|
||||
}
|
||||
|
||||
if len(actions) > 0 {
|
||||
actionsJSON, err := json.Marshal(actions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Actions = actionsJSON
|
||||
} else {
|
||||
op.Actions = "[]"
|
||||
}
|
||||
|
||||
op.State = NodeIPAddressThresholdStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateThreshold 修改阈值
|
||||
func (this *NodeIPAddressThresholdDAO) UpdateThreshold(tx *dbs.Tx, thresholdId int64, items []*nodeconfigs.IPAddressThresholdItemConfig, actions []*nodeconfigs.IPAddressThresholdActionConfig, order int) error {
|
||||
if thresholdId <= 0 {
|
||||
return errors.New("invalid thresholdId")
|
||||
}
|
||||
var op = NewNodeIPAddressThresholdOperator()
|
||||
|
||||
op.State = NodeIPAddressThresholdStateEnabled // 恢复状态
|
||||
if order >= 0 {
|
||||
op.Order = order
|
||||
}
|
||||
|
||||
op.Id = thresholdId
|
||||
|
||||
if len(items) > 0 {
|
||||
itemsJSON, err := json.Marshal(items)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Items = itemsJSON
|
||||
} else {
|
||||
op.Items = "[]"
|
||||
}
|
||||
|
||||
if len(actions) > 0 {
|
||||
actionsJSON, err := json.Marshal(actions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Actions = actionsJSON
|
||||
} else {
|
||||
op.Actions = "[]"
|
||||
}
|
||||
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// DisableAllThresholdsWithAddrId 禁用所有阈值
|
||||
func (this *NodeIPAddressThresholdDAO) DisableAllThresholdsWithAddrId(tx *dbs.Tx, addrId int64) error {
|
||||
return this.Query(tx).
|
||||
Attr("addressId", addrId).
|
||||
Set("state", NodeIPAddressThresholdStateDisabled).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// 格式化阈值
|
||||
func (this *NodeIPAddressThresholdDAO) formatThreshold(tx *dbs.Tx, threshold *NodeIPAddressThreshold) error {
|
||||
if len(threshold.Items) == 0 {
|
||||
return nil
|
||||
}
|
||||
var items = threshold.DecodeItems()
|
||||
for _, item := range items {
|
||||
if item.Item == nodeconfigs.IPAddressThresholdItemConnectivity {
|
||||
if item.Options == nil {
|
||||
continue
|
||||
}
|
||||
var groups = item.Options.GetSlice("groups")
|
||||
if len(groups) > 0 {
|
||||
var newGroups = []maps.Map{}
|
||||
for _, groupOne := range groups {
|
||||
var groupMap = maps.NewMap(groupOne)
|
||||
var groupId = groupMap.GetInt64("id")
|
||||
group, err := SharedReportNodeGroupDAO.FindEnabledReportNodeGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
newGroups = append(newGroups, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
item.Options["groups"] = newGroups
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemsJSON, err := json.Marshal(items)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
threshold.Items = string(itemsJSON)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsEnabledThreshold 检查阈值是否可以使用
|
||||
func (this *NodeIPAddressThresholdDAO) ExistsEnabledThreshold(tx *dbs.Tx, thresholdId int64) (bool, error) {
|
||||
return this.Query(tx).
|
||||
Pk(thresholdId).
|
||||
State(NodeIPAddressThresholdStateEnabled).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// UpdateThresholdIsMatched 设置是否匹配
|
||||
func (this *NodeIPAddressThresholdDAO) UpdateThresholdIsMatched(tx *dbs.Tx, thresholdId int64, isMatched bool) error {
|
||||
return this.Query(tx).
|
||||
Pk(thresholdId).
|
||||
Set("isMatched", isMatched).
|
||||
UpdateQuickly()
|
||||
}
|
||||
6
internal/db/models/node_ip_address_threshold_dao_test.go
Normal file
6
internal/db/models/node_ip_address_threshold_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
28
internal/db/models/node_ip_address_threshold_model.go
Normal file
28
internal/db/models/node_ip_address_threshold_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
// NodeIPAddressThreshold IP地址阈值
|
||||
type NodeIPAddressThreshold struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AddressId uint64 `field:"addressId"` // IP地址ID
|
||||
Items string `field:"items"` // 阈值条目
|
||||
Actions string `field:"actions"` // 动作
|
||||
NotifiedAt uint64 `field:"notifiedAt"` // 上次通知时间
|
||||
IsMatched uint8 `field:"isMatched"` // 上次是否匹配
|
||||
State uint8 `field:"state"` // 状态
|
||||
Order uint32 `field:"order"` // 排序
|
||||
}
|
||||
|
||||
type NodeIPAddressThresholdOperator struct {
|
||||
Id interface{} // ID
|
||||
AddressId interface{} // IP地址ID
|
||||
Items interface{} // 阈值条目
|
||||
Actions interface{} // 动作
|
||||
NotifiedAt interface{} // 上次通知时间
|
||||
IsMatched interface{} // 上次是否匹配
|
||||
State interface{} // 状态
|
||||
Order interface{} // 排序
|
||||
}
|
||||
|
||||
func NewNodeIPAddressThresholdOperator() *NodeIPAddressThresholdOperator {
|
||||
return &NodeIPAddressThresholdOperator{}
|
||||
}
|
||||
31
internal/db/models/node_ip_address_threshold_model_ext.go
Normal file
31
internal/db/models/node_ip_address_threshold_model_ext.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
)
|
||||
|
||||
func (this *NodeIPAddressThreshold) DecodeItems() (result []*nodeconfigs.IPAddressThresholdItemConfig) {
|
||||
if len(this.Items) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(this.Items), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeIPAddressThreshold", "decode items: "+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *NodeIPAddressThreshold) DecodeActions() (result []*nodeconfigs.IPAddressThresholdActionConfig) {
|
||||
if len(this.Actions) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(this.Actions), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeIPAddressThreshold", "decode actions: "+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -65,6 +66,11 @@ func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error)
|
||||
return nil, err
|
||||
}
|
||||
domainRoutes, _ := routes[dnsDomainId]
|
||||
|
||||
if len(domainRoutes) > 0 {
|
||||
sort.Strings(domainRoutes)
|
||||
}
|
||||
|
||||
return domainRoutes, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ func (this *NodeThresholdDAO) FireNodeThreshold(tx *dbs.Tx, role string, nodeId
|
||||
if len(threshold.Param) == 0 || threshold.Duration <= 0 {
|
||||
continue
|
||||
}
|
||||
paramValue, err := SharedNodeValueDAO.SumValues(tx, role, nodeId, item, threshold.Param, threshold.SumMethod, types.Int32(threshold.Duration), threshold.DurationUnit)
|
||||
paramValue, err := SharedNodeValueDAO.SumNodeValues(tx, role, nodeId, item, threshold.Param, threshold.SumMethod, types.Int32(threshold.Duration), threshold.DurationUnit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -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, role, clusterId, nodeId, MessageTypeThresholdSatisfied, MessageLevelWarning, subject, body, maps.Map{}.AsJSON())
|
||||
err = SharedMessageDAO.CreateNodeMessage(tx, role, clusterId, nodeId, MessageTypeThresholdSatisfied, MessageLevelWarning, subject, body, maps.Map{}.AsJSON(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -173,8 +173,8 @@ func (this *NodeValueDAO) ListValuesForNSNodes(tx *dbs.Tx, item string, key stri
|
||||
return
|
||||
}
|
||||
|
||||
// SumValues 计算某项参数值
|
||||
func (this *NodeValueDAO) SumValues(tx *dbs.Tx, role string, nodeId int64, item string, param string, method nodeconfigs.NodeValueSumMethod, duration int32, durationUnit nodeconfigs.NodeValueDurationUnit) (float64, error) {
|
||||
// SumNodeValues 计算节点的某项参数值
|
||||
func (this *NodeValueDAO) SumNodeValues(tx *dbs.Tx, role string, nodeId int64, item string, param string, method nodeconfigs.NodeValueSumMethod, duration int32, durationUnit nodeconfigs.NodeValueDurationUnit) (float64, error) {
|
||||
if duration <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -202,6 +202,65 @@ func (this *NodeValueDAO) SumValues(tx *dbs.Tx, role string, nodeId int64, item
|
||||
return query.FindFloat64Col(0)
|
||||
}
|
||||
|
||||
// SumNodeGroupValues 计算节点分组的某项参数值
|
||||
func (this *NodeValueDAO) SumNodeGroupValues(tx *dbs.Tx, role string, groupId int64, item string, param string, method nodeconfigs.NodeValueSumMethod, duration int32, durationUnit nodeconfigs.NodeValueDurationUnit) (float64, error) {
|
||||
if duration <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
query := this.Query(tx).
|
||||
Attr("role", role).
|
||||
Where("nodeId IN (SELECT id FROM "+SharedNodeDAO.Table+" WHERE groupId=:groupId AND state=1)").
|
||||
Param("groupId", groupId).
|
||||
Attr("item", item)
|
||||
switch method {
|
||||
case nodeconfigs.NodeValueSumMethodAvg:
|
||||
query.Result("AVG(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
case nodeconfigs.NodeValueSumMethodSum:
|
||||
query.Result("SUM(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
default:
|
||||
query.Result("AVG(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
}
|
||||
switch durationUnit {
|
||||
case nodeconfigs.NodeValueDurationUnitMinute:
|
||||
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(duration*60))
|
||||
query.Gte("minute", fromMinute)
|
||||
default:
|
||||
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(duration*60))
|
||||
query.Gte("minute", fromMinute)
|
||||
}
|
||||
return query.FindFloat64Col(0)
|
||||
}
|
||||
|
||||
// SumNodeClusterValues 计算节点集群的某项参数值
|
||||
func (this *NodeValueDAO) SumNodeClusterValues(tx *dbs.Tx, role string, clusterId int64, item string, param string, method nodeconfigs.NodeValueSumMethod, duration int32, durationUnit nodeconfigs.NodeValueDurationUnit) (float64, error) {
|
||||
if duration <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
query := this.Query(tx).
|
||||
Attr("role", role).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("item", item)
|
||||
switch method {
|
||||
case nodeconfigs.NodeValueSumMethodAvg:
|
||||
query.Result("AVG(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
case nodeconfigs.NodeValueSumMethodSum:
|
||||
query.Result("SUM(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
default:
|
||||
query.Result("AVG(JSON_EXTRACT(value, '$." + param + "'))")
|
||||
}
|
||||
switch durationUnit {
|
||||
case nodeconfigs.NodeValueDurationUnitMinute:
|
||||
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(duration*60))
|
||||
query.Gte("minute", fromMinute)
|
||||
default:
|
||||
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(duration*60))
|
||||
query.Gte("minute", fromMinute)
|
||||
}
|
||||
return query.FindFloat64Col(0)
|
||||
}
|
||||
|
||||
// FindLatestNodeValue 获取最近一条数据
|
||||
func (this *NodeValueDAO) FindLatestNodeValue(tx *dbs.Tx, role string, nodeId int64, item string) (*NodeValue, error) {
|
||||
one, err := this.Query(tx).
|
||||
|
||||
@@ -87,7 +87,7 @@ func (this *OriginDAO) FindOriginName(tx *dbs.Tx, id int64) (string, error) {
|
||||
}
|
||||
|
||||
// CreateOrigin 创建源站
|
||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32) (originId int64, err error) {
|
||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) (originId int64, err error) {
|
||||
op := NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -132,6 +132,17 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
||||
weight = 0
|
||||
}
|
||||
op.Weight = weight
|
||||
|
||||
if len(domains) > 0 {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
} else {
|
||||
op.Domains = "[]"
|
||||
}
|
||||
|
||||
op.State = OriginStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -141,7 +152,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
||||
}
|
||||
|
||||
// UpdateOrigin 修改源站
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32) error {
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
}
|
||||
@@ -189,6 +200,17 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, add
|
||||
|
||||
op.IsOn = isOn
|
||||
op.Version = dbs.SQL("version+1")
|
||||
|
||||
if len(domains) > 0 {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
} else {
|
||||
op.Domains = "[]"
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -229,6 +251,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
MaxIdleConns: int(origin.MaxIdleConns),
|
||||
RequestURI: origin.HttpRequestURI,
|
||||
RequestHost: origin.Host,
|
||||
Domains: origin.DecodeDomains(),
|
||||
}
|
||||
|
||||
if IsNotNull(origin.Addr) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 源站
|
||||
// Origin 源站
|
||||
type Origin struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
@@ -26,6 +26,7 @@ type Origin struct {
|
||||
Cert string `field:"cert"` // 证书设置
|
||||
Ftp string `field:"ftp"` // FTP相关设置
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Domains string `field:"domains"` // 所属域名
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
@@ -54,6 +55,7 @@ type OriginOperator struct {
|
||||
Cert interface{} // 证书设置
|
||||
Ftp interface{} // FTP相关设置
|
||||
CreatedAt interface{} // 创建时间
|
||||
Domains interface{} // 所属域名
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
)
|
||||
|
||||
// 解析地址
|
||||
// DecodeAddr 解析地址
|
||||
func (this *Origin) DecodeAddr() (*serverconfigs.NetworkAddressConfig, error) {
|
||||
if len(this.Addr) == 0 || this.Addr == "null" {
|
||||
return nil, errors.New("addr is empty")
|
||||
@@ -15,3 +16,14 @@ func (this *Origin) DecodeAddr() (*serverconfigs.NetworkAddressConfig, error) {
|
||||
err := json.Unmarshal([]byte(this.Addr), addr)
|
||||
return addr, err
|
||||
}
|
||||
|
||||
func (this *Origin) DecodeDomains() []string {
|
||||
var result = []string{}
|
||||
if len(this.Domains) > 0 {
|
||||
err := json.Unmarshal([]byte(this.Domains), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("Origin.DecodeDomains", err.Error())
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -76,7 +78,7 @@ func (this *ReportNodeDAO) FindReportNodeName(tx *dbs.Tx, id int64) (string, err
|
||||
}
|
||||
|
||||
// CreateReportNode 创建终端
|
||||
func (this *ReportNodeDAO) CreateReportNode(tx *dbs.Tx, name string, location string, isp string, allowIPs []string) (int64, error) {
|
||||
func (this *ReportNodeDAO) CreateReportNode(tx *dbs.Tx, name string, location string, isp string, allowIPs []string, groupIds []int64) (int64, error) {
|
||||
uniqueId, err := this.GenUniqueId(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -107,13 +109,23 @@ func (this *ReportNodeDAO) CreateReportNode(tx *dbs.Tx, name string, location st
|
||||
op.AllowIPs = "[]"
|
||||
}
|
||||
|
||||
if len(groupIds) > 0 {
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.GroupIds = groupIdsJSON
|
||||
} else {
|
||||
op.GroupIds = "[]"
|
||||
}
|
||||
|
||||
op.IsOn = true
|
||||
op.State = ReportNodeStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateReportNode 修改终端
|
||||
func (this *ReportNodeDAO) UpdateReportNode(tx *dbs.Tx, nodeId int64, name string, location string, isp string, allowIPs []string, isOn bool) error {
|
||||
func (this *ReportNodeDAO) UpdateReportNode(tx *dbs.Tx, nodeId int64, name string, location string, isp string, allowIPs []string, groupIds []int64, isOn bool) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
@@ -134,14 +146,27 @@ func (this *ReportNodeDAO) UpdateReportNode(tx *dbs.Tx, nodeId int64, name strin
|
||||
op.AllowIPs = "[]"
|
||||
}
|
||||
|
||||
if len(groupIds) > 0 {
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.GroupIds = groupIdsJSON
|
||||
} else {
|
||||
op.GroupIds = "[]"
|
||||
}
|
||||
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CountAllEnabledReportNodes 计算终端数量
|
||||
func (this *ReportNodeDAO) CountAllEnabledReportNodes(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
func (this *ReportNodeDAO) CountAllEnabledReportNodes(tx *dbs.Tx, groupId int64, keyword string) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(ReportNodeStateEnabled)
|
||||
if groupId > 0 {
|
||||
query.JSONContains("groupIds", types.String(groupId))
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR location LIKE :keyword OR isp LIKE :keyword OR allowIPs LIKE :keyword OR (status IS NOT NULL AND JSON_EXTRACT(status, 'ip') LIKE :keyword))")
|
||||
query.Param("keyword", "%"+keyword+"%")
|
||||
@@ -149,10 +174,21 @@ func (this *ReportNodeDAO) CountAllEnabledReportNodes(tx *dbs.Tx, keyword string
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// CountAllEnabledAndOnReportNodes 计算可用的终端数量
|
||||
func (this *ReportNodeDAO) CountAllEnabledAndOnReportNodes(tx *dbs.Tx) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("isOn", true).
|
||||
State(ReportNodeStateEnabled)
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledReportNodes 列出单页终端
|
||||
func (this *ReportNodeDAO) ListEnabledReportNodes(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*ReportNode, err error) {
|
||||
func (this *ReportNodeDAO) ListEnabledReportNodes(tx *dbs.Tx, groupId int64, keyword string, offset int64, size int64) (result []*ReportNode, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(ReportNodeStateEnabled)
|
||||
if groupId > 0 {
|
||||
query.JSONContains("groupIds", types.String(groupId))
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where(`(
|
||||
name LIKE :keyword
|
||||
@@ -267,3 +303,13 @@ func (this *ReportNodeDAO) FindNodeAllowIPs(tx *dbs.Tx, nodeId int64) ([]string,
|
||||
}
|
||||
return node.(*ReportNode).DecodeAllowIPs(), nil
|
||||
}
|
||||
|
||||
// CountAllLowerVersionNodes 计算所有节点中低于某个版本的节点数量
|
||||
func (this *ReportNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(ReportNodeStateEnabled).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
Count()
|
||||
}
|
||||
|
||||
109
internal/db/models/report_node_group_dao.go
Normal file
109
internal/db/models/report_node_group_dao.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
ReportNodeGroupStateEnabled = 1 // 已启用
|
||||
ReportNodeGroupStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type ReportNodeGroupDAO dbs.DAO
|
||||
|
||||
func NewReportNodeGroupDAO() *ReportNodeGroupDAO {
|
||||
return dbs.NewDAO(&ReportNodeGroupDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeReportNodeGroups",
|
||||
Model: new(ReportNodeGroup),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*ReportNodeGroupDAO)
|
||||
}
|
||||
|
||||
var SharedReportNodeGroupDAO *ReportNodeGroupDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedReportNodeGroupDAO = NewReportNodeGroupDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableReportNodeGroup 启用条目
|
||||
func (this *ReportNodeGroupDAO) EnableReportNodeGroup(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", ReportNodeGroupStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableReportNodeGroup 禁用条目
|
||||
func (this *ReportNodeGroupDAO) DisableReportNodeGroup(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", ReportNodeGroupStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledReportNodeGroup 查找启用中的条目
|
||||
func (this *ReportNodeGroupDAO) FindEnabledReportNodeGroup(tx *dbs.Tx, id int64) (*ReportNodeGroup, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", ReportNodeGroupStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*ReportNodeGroup), err
|
||||
}
|
||||
|
||||
// FindReportNodeGroupName 根据主键查找名称
|
||||
func (this *ReportNodeGroupDAO) FindReportNodeGroupName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateGroup 创建
|
||||
func (this *ReportNodeGroupDAO) CreateGroup(tx *dbs.Tx, name string) (int64, error) {
|
||||
var op = NewReportNodeGroupOperator()
|
||||
op.Name = name
|
||||
op.IsOn = true
|
||||
op.State = ReportNodeGroupStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateGroup 修改
|
||||
func (this *ReportNodeGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
}
|
||||
var op = NewReportNodeGroupOperator()
|
||||
op.Id = groupId
|
||||
op.Name = name
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// FindAllEnabledGroups 查找所有可用的分组
|
||||
func (this *ReportNodeGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ReportNodeGroup, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(ReportNodeGroupStateEnabled).
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllEnabledGroups 查找所有分组的数量
|
||||
func (this *ReportNodeGroupDAO) CountAllEnabledGroups(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(ReportNodeGroupStateEnabled).
|
||||
Count()
|
||||
}
|
||||
6
internal/db/models/report_node_group_dao_test.go
Normal file
6
internal/db/models/report_node_group_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
20
internal/db/models/report_node_group_model.go
Normal file
20
internal/db/models/report_node_group_model.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
// ReportNodeGroup 监控终端区域
|
||||
type ReportNodeGroup struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 名称
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
}
|
||||
|
||||
type ReportNodeGroupOperator struct {
|
||||
Id interface{} // ID
|
||||
Name interface{} // 名称
|
||||
State interface{} // 状态
|
||||
IsOn interface{} // 是否启用
|
||||
}
|
||||
|
||||
func NewReportNodeGroupOperator() *ReportNodeGroupOperator {
|
||||
return &ReportNodeGroupOperator{}
|
||||
}
|
||||
1
internal/db/models/report_node_group_model_ext.go
Normal file
1
internal/db/models/report_node_group_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -14,6 +14,7 @@ type ReportNode struct {
|
||||
Status string `field:"status"` // 状态
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
GroupIds string `field:"groupIds"` // 分组ID
|
||||
}
|
||||
|
||||
type ReportNodeOperator struct {
|
||||
@@ -29,6 +30,7 @@ type ReportNodeOperator struct {
|
||||
Status interface{} // 状态
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
GroupIds interface{} // 分组ID
|
||||
}
|
||||
|
||||
func NewReportNodeOperator() *ReportNodeOperator {
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
)
|
||||
|
||||
func (this *ReportNode) DecodeAllowIPs() []string {
|
||||
var result = []string{}
|
||||
if len(this.AllowIPs) > 0 {
|
||||
// 忽略错误
|
||||
_ = json.Unmarshal([]byte(this.AllowIPs), &result)
|
||||
err := json.Unmarshal([]byte(this.AllowIPs), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("ReportNode.DecodeGroupIds", err.Error())
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (this *ReportNode) DecodeGroupIds() []int64 {
|
||||
var result = []int64{}
|
||||
if len(this.GroupIds) > 0 {
|
||||
err := json.Unmarshal([]byte(this.GroupIds), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("ReportNode.DecodeGroupIds", err.Error())
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -31,7 +33,7 @@ func init() {
|
||||
}
|
||||
|
||||
// UpdateResult 创建结果
|
||||
func (this *ReportResultDAO) UpdateResult(tx *dbs.Tx, taskType string, targetId int64, targetDesc string, reportNodeId int64, isOk bool, costMs float64, errString string) error {
|
||||
func (this *ReportResultDAO) UpdateResult(tx *dbs.Tx, taskType string, targetId int64, targetDesc string, reportNodeId int64, level reporterconfigs.ReportLevel, isOk bool, costMs float64, errString string) error {
|
||||
var countUp interface{} = 0
|
||||
var countDown interface{} = 0
|
||||
if isOk {
|
||||
@@ -52,6 +54,7 @@ func (this *ReportResultDAO) UpdateResult(tx *dbs.Tx, taskType string, targetId
|
||||
"error": errString,
|
||||
"countUp": countUp,
|
||||
"countDown": countDown,
|
||||
"level": level,
|
||||
}, maps.Map{
|
||||
"targetDesc": targetDesc,
|
||||
"updatedAt": time.Now().Unix(),
|
||||
@@ -60,11 +63,12 @@ func (this *ReportResultDAO) UpdateResult(tx *dbs.Tx, taskType string, targetId
|
||||
"error": errString,
|
||||
"countUp": countUp,
|
||||
"countDown": countDown,
|
||||
"level": level,
|
||||
})
|
||||
}
|
||||
|
||||
// CountAllResults 计算结果数量
|
||||
func (this *ReportResultDAO) CountAllResults(tx *dbs.Tx, reportNodeId int64, okState configutils.BoolState) (int64, error) {
|
||||
func (this *ReportResultDAO) CountAllResults(tx *dbs.Tx, reportNodeId int64, level reporterconfigs.ReportLevel, okState configutils.BoolState) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("reportNodeId", reportNodeId)
|
||||
switch okState {
|
||||
@@ -73,12 +77,16 @@ func (this *ReportResultDAO) CountAllResults(tx *dbs.Tx, reportNodeId int64, okS
|
||||
case configutils.BoolStateNo:
|
||||
query.Attr("isOk", 0)
|
||||
}
|
||||
if len(level) > 0 {
|
||||
query.Attr("level", level)
|
||||
}
|
||||
return query.
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListResults 列出单页结果
|
||||
func (this *ReportResultDAO) ListResults(tx *dbs.Tx, reportNodeId int64, okState configutils.BoolState, offset int64, size int64) (result []*ReportResult, err error) {
|
||||
func (this *ReportResultDAO) ListResults(tx *dbs.Tx, reportNodeId int64, okState configutils.BoolState, level reporterconfigs.ReportLevel, offset int64, size int64) (result []*ReportResult, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("reportNodeId", reportNodeId)
|
||||
switch okState {
|
||||
@@ -87,8 +95,11 @@ func (this *ReportResultDAO) ListResults(tx *dbs.Tx, reportNodeId int64, okState
|
||||
case configutils.BoolStateNo:
|
||||
query.Attr("isOk", 0)
|
||||
}
|
||||
if len(level) > 0 {
|
||||
query.Attr("level", level)
|
||||
}
|
||||
_, err = query.
|
||||
Attr("reportNodeId", reportNodeId).
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Desc("targetId").
|
||||
@@ -96,3 +107,116 @@ func (this *ReportResultDAO) ListResults(tx *dbs.Tx, reportNodeId int64, okState
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllResults 列出所有结果
|
||||
func (this *ReportResultDAO) FindAllResults(tx *dbs.Tx, taskType string, targetId int64) (result []*ReportResult, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("type", taskType).
|
||||
Attr("targetId", targetId).
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Desc("isOk").
|
||||
Asc("costMs").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindAvgCostMsWithTarget 获取某个对象的平均耗时
|
||||
func (this *ReportResultDAO) FindAvgCostMsWithTarget(tx *dbs.Tx, taskType reporterconfigs.TaskType, targetId int64) (float64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("type", taskType).
|
||||
Attr("targetId", targetId).
|
||||
Where("reportNodeId IN (SELECT id FROM "+SharedReportNodeDAO.Table+" WHERE state=1 AND isOn=1)").
|
||||
Attr("isOk", true).
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Avg("costMs", 0)
|
||||
}
|
||||
|
||||
// FindAvgLevelWithTarget 获取某个对象的平均级别
|
||||
func (this *ReportResultDAO) FindAvgLevelWithTarget(tx *dbs.Tx, taskType reporterconfigs.TaskType, targetId int64) (string, error) {
|
||||
ones, _, err := this.Query(tx).
|
||||
Result("COUNT(*) AS c, level").
|
||||
Attr("type", taskType).
|
||||
Attr("targetId", targetId).
|
||||
Where("reportNodeId IN (SELECT id FROM "+SharedReportNodeDAO.Table+" WHERE state=1 AND isOn=1)").
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Group("level").
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(ones) == 0 {
|
||||
return reporterconfigs.ReportLevelNormal, nil
|
||||
}
|
||||
|
||||
var total = 0
|
||||
var levelMap = map[string]int{} // code => count
|
||||
for _, one := range ones {
|
||||
var c = one.GetInt("c")
|
||||
total += c
|
||||
levelMap[one.GetString("level")] = c
|
||||
}
|
||||
if total == 0 {
|
||||
return reporterconfigs.ReportLevelNormal, nil
|
||||
}
|
||||
|
||||
var half = total / 2
|
||||
for _, def := range reporterconfigs.FindAllReportLevels() {
|
||||
c, ok := levelMap[def.Code]
|
||||
if ok {
|
||||
half -= c
|
||||
if half <= 0 {
|
||||
return def.Code, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// FindConnectivityWithTargetPercent 获取某个对象的连通率
|
||||
// 返回值在0-100
|
||||
func (this *ReportResultDAO) FindConnectivityWithTargetPercent(tx *dbs.Tx, taskType reporterconfigs.TaskType, targetId int64, groupId int64) (float64, error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("type", taskType).
|
||||
Attr("targetId", targetId)
|
||||
if groupId > 0 {
|
||||
query.Where("reportNodeId IN (SELECT id FROM "+SharedReportNodeDAO.Table+" WHERE state=1 AND isOn=1 AND JSON_CONTAINS(groupIds, :groupIdString))").
|
||||
Param("groupIdString", types.String(groupId))
|
||||
} else {
|
||||
query.Where("reportNodeId IN (SELECT id FROM " + SharedReportNodeDAO.Table + " WHERE state=1 AND isOn=1)")
|
||||
}
|
||||
|
||||
// 已汇报数据的数量
|
||||
total, err := query.
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 100, nil
|
||||
}
|
||||
|
||||
// 连通的数量
|
||||
var connectedQuery = this.Query(tx).
|
||||
Attr("type", taskType).
|
||||
Attr("targetId", targetId)
|
||||
|
||||
if groupId > 0 {
|
||||
connectedQuery.Where("reportNodeId IN (SELECT id FROM "+SharedReportNodeDAO.Table+" WHERE state=1 AND isOn=1 AND JSON_CONTAINS(groupIds, :groupIdString))").
|
||||
Param("groupIdString", types.String(groupId))
|
||||
} else {
|
||||
connectedQuery.Where("reportNodeId IN (SELECT id FROM " + SharedReportNodeDAO.Table + " WHERE state=1 AND isOn=1)")
|
||||
}
|
||||
|
||||
countConnected, err := connectedQuery.
|
||||
Attr("isOk", true).
|
||||
Gt("updatedAt", time.Now().Unix()-600).
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float64(countConnected) * 100 / float64(total), nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ type ReportResult struct {
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
|
||||
ReportNodeId uint32 `field:"reportNodeId"` // 监控节点ID
|
||||
IsOk uint8 `field:"isOk"` // 是否可连接
|
||||
Level string `field:"level"` // 级别
|
||||
CostMs float64 `field:"costMs"` // 单次连接花费的时间
|
||||
Error string `field:"error"` // 产生的错误信息
|
||||
CountUp uint32 `field:"countUp"` // 连续上线次数
|
||||
@@ -23,6 +24,7 @@ type ReportResultOperator struct {
|
||||
UpdatedAt interface{} // 更新时间
|
||||
ReportNodeId interface{} // 监控节点ID
|
||||
IsOk interface{} // 是否可连接
|
||||
Level interface{} // 级别
|
||||
CostMs interface{} // 单次连接花费的时间
|
||||
Error interface{} // 产生的错误信息
|
||||
CountUp interface{} // 连续上线次数
|
||||
|
||||
@@ -406,5 +406,14 @@ func (this *ReverseProxyDAO) NotifyUpdate(tx *dbs.Tx, reverseProxyId int64) erro
|
||||
return SharedHTTPLocationDAO.NotifyUpdate(tx, locationId)
|
||||
}
|
||||
|
||||
// group
|
||||
groupId, err := SharedServerGroupDAO.FindEnabledGroupIdWithReverseProxyId(tx, reverseProxyId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupId > 0 {
|
||||
return SharedServerGroupDAO.NotifyUpdate(tx, groupId)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -713,6 +713,44 @@ func (this *ServerDAO) FindAllEnabledServerIdsWithUserId(tx *dbs.Tx, userId int6
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllEnabledServerIdsWithGroupId 获取某个分组下的所有的服务ID
|
||||
func (this *ServerDAO) FindAllEnabledServerIdsWithGroupId(tx *dbs.Tx, groupId int64) (serverIds []int64, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_CONTAINS(groupIds, :groupId)").
|
||||
Param("groupId", numberutils.FormatInt64(groupId)).
|
||||
AscPk().
|
||||
ResultPk().
|
||||
FindAll()
|
||||
for _, one := range ones {
|
||||
serverIds = append(serverIds, int64(one.(*Server).Id))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindServerGroupIds 获取服务的分组ID
|
||||
func (this *ServerDAO) FindServerGroupIds(tx *dbs.Tx, serverId int64) ([]int64, error) {
|
||||
if serverId <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
groupIdsString, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("groupIds").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(groupIdsString) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var result = []int64{}
|
||||
err = json.Unmarshal([]byte(groupIdsString), &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindServerNodeFilters 查找服务的搜索条件
|
||||
func (this *ServerDAO) FindServerNodeFilters(tx *dbs.Tx, serverId int64) (isOk bool, clusterId int64, err error) {
|
||||
one, err := this.Query(tx).
|
||||
@@ -760,6 +798,20 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
config.Name = server.Name
|
||||
config.Description = server.Description
|
||||
|
||||
var groupConfig *serverconfigs.ServerGroupConfig
|
||||
for _, groupId := range server.DecodeGroupIds() {
|
||||
groupConfig1, err := SharedServerGroupDAO.ComposeGroupConfig(tx, groupId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if groupConfig1 == nil {
|
||||
continue
|
||||
}
|
||||
groupConfig = groupConfig1
|
||||
break
|
||||
}
|
||||
config.Group = groupConfig
|
||||
|
||||
// ServerNames
|
||||
if len(server.ServerNames) > 0 && server.ServerNames != "null" {
|
||||
serverNames := []*serverconfigs.ServerNameConfig{}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -34,7 +37,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableServerGroup 启用条目
|
||||
func (this *ServerGroupDAO) EnableServerGroup(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -43,7 +46,7 @@ func (this *ServerGroupDAO) EnableServerGroup(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableServerGroup 禁用条目
|
||||
func (this *ServerGroupDAO) DisableServerGroup(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -52,7 +55,7 @@ func (this *ServerGroupDAO) DisableServerGroup(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledServerGroup 查找启用中的条目
|
||||
func (this *ServerGroupDAO) FindEnabledServerGroup(tx *dbs.Tx, id int64) (*ServerGroup, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -64,7 +67,7 @@ func (this *ServerGroupDAO) FindEnabledServerGroup(tx *dbs.Tx, id int64) (*Serve
|
||||
return result.(*ServerGroup), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindServerGroupName 根据主键查找名称
|
||||
func (this *ServerGroupDAO) FindServerGroupName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -72,11 +75,12 @@ func (this *ServerGroupDAO) FindServerGroupName(tx *dbs.Tx, id int64) (string, e
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 创建分组
|
||||
// CreateGroup 创建分组
|
||||
func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string) (groupId int64, err error) {
|
||||
op := NewServerGroupOperator()
|
||||
op.State = ServerGroupStateEnabled
|
||||
op.Name = name
|
||||
op.IsOn = true
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -84,7 +88,7 @@ func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string) (groupId int64,
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 修改分组
|
||||
// UpdateGroup 修改分组
|
||||
func (this *ServerGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
@@ -96,7 +100,7 @@ func (this *ServerGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string)
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找所有分组
|
||||
// FindAllEnabledGroups 查找所有分组
|
||||
func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGroup, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(ServerGroupStateEnabled).
|
||||
@@ -107,7 +111,7 @@ func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGr
|
||||
return
|
||||
}
|
||||
|
||||
// 修改分组排序
|
||||
// UpdateGroupOrders 修改分组排序
|
||||
func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64) error {
|
||||
for index, groupId := range groupIds {
|
||||
_, err := this.Query(tx).
|
||||
@@ -120,3 +124,221 @@ func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindHTTPReverseProxyRef 根据条件获取HTTP反向代理配置
|
||||
func (this *ServerGroupDAO) FindHTTPReverseProxyRef(tx *dbs.Tx, groupId int64) (*serverconfigs.ReverseProxyRef, error) {
|
||||
reverseProxy, err := this.Query(tx).
|
||||
Pk(groupId).
|
||||
Result("httpReverseProxy").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(reverseProxy) == 0 || reverseProxy == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(reverseProxy), config)
|
||||
return config, err
|
||||
}
|
||||
|
||||
// FindTCPReverseProxyRef 根据条件获取TCP反向代理配置
|
||||
func (this *ServerGroupDAO) FindTCPReverseProxyRef(tx *dbs.Tx, groupId int64) (*serverconfigs.ReverseProxyRef, error) {
|
||||
reverseProxy, err := this.Query(tx).
|
||||
Pk(groupId).
|
||||
Result("tcpReverseProxy").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(reverseProxy) == 0 || reverseProxy == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(reverseProxy), config)
|
||||
return config, err
|
||||
}
|
||||
|
||||
// FindUDPReverseProxyRef 根据条件获取UDP反向代理配置
|
||||
func (this *ServerGroupDAO) FindUDPReverseProxyRef(tx *dbs.Tx, groupId int64) (*serverconfigs.ReverseProxyRef, error) {
|
||||
reverseProxy, err := this.Query(tx).
|
||||
Pk(groupId).
|
||||
Result("udpReverseProxy").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(reverseProxy) == 0 || reverseProxy == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(reverseProxy), config)
|
||||
return config, err
|
||||
}
|
||||
|
||||
// UpdateHTTPReverseProxy 修改HTTP反向代理配置
|
||||
func (this *ServerGroupDAO) UpdateHTTPReverseProxy(tx *dbs.Tx, groupId int64, config []byte) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("groupId should not be smaller than 0")
|
||||
}
|
||||
op := NewServerGroupOperator()
|
||||
op.Id = groupId
|
||||
op.HttpReverseProxy = JSONBytes(config)
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, groupId)
|
||||
}
|
||||
|
||||
// UpdateTCPReverseProxy 修改TCP反向代理配置
|
||||
func (this *ServerGroupDAO) UpdateTCPReverseProxy(tx *dbs.Tx, groupId int64, config []byte) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("groupId should not be smaller than 0")
|
||||
}
|
||||
op := NewServerGroupOperator()
|
||||
op.Id = groupId
|
||||
op.TcpReverseProxy = JSONBytes(config)
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, groupId)
|
||||
}
|
||||
|
||||
// UpdateUDPReverseProxy 修改UDP反向代理配置
|
||||
func (this *ServerGroupDAO) UpdateUDPReverseProxy(tx *dbs.Tx, groupId int64, config []byte) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("groupId should not be smaller than 0")
|
||||
}
|
||||
op := NewServerGroupOperator()
|
||||
op.Id = groupId
|
||||
op.UdpReverseProxy = JSONBytes(config)
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, groupId)
|
||||
}
|
||||
|
||||
// ComposeGroupConfig 组合配置
|
||||
func (this *ServerGroupDAO) ComposeGroupConfig(tx *dbs.Tx, groupId int64, cacheMap maps.Map) (*serverconfigs.ServerGroupConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
}
|
||||
|
||||
var cacheKey = this.Table + ":config:" + types.String(groupId)
|
||||
var cacheConfig = cacheMap.Get(cacheKey)
|
||||
if cacheConfig != nil {
|
||||
// 克隆,防止分解后的Server配置相互受到影响
|
||||
configJSON, err := json.Marshal(cacheConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var clonedConfig = &serverconfigs.ServerGroupConfig{}
|
||||
err = json.Unmarshal(configJSON, clonedConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return clonedConfig, nil
|
||||
}
|
||||
|
||||
group, err := this.FindEnabledServerGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var config = &serverconfigs.ServerGroupConfig{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn == 1,
|
||||
}
|
||||
|
||||
if len(group.HttpReverseProxy) > 0 {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
err := json.Unmarshal([]byte(group.HttpReverseProxy), reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.HTTPReverseProxyRef = reverseProxyRef
|
||||
|
||||
reverseProxyConfig, err := SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reverseProxyConfig != nil {
|
||||
config.HTTPReverseProxy = reverseProxyConfig
|
||||
}
|
||||
}
|
||||
|
||||
if len(group.TcpReverseProxy) > 0 {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
err := json.Unmarshal([]byte(group.TcpReverseProxy), reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.TCPReverseProxyRef = reverseProxyRef
|
||||
|
||||
reverseProxyConfig, err := SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reverseProxyConfig != nil {
|
||||
config.TCPReverseProxy = reverseProxyConfig
|
||||
}
|
||||
}
|
||||
|
||||
if len(group.UdpReverseProxy) > 0 {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
err := json.Unmarshal([]byte(group.UdpReverseProxy), reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.UDPReverseProxyRef = reverseProxyRef
|
||||
|
||||
reverseProxyConfig, err := SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reverseProxyConfig != nil {
|
||||
config.UDPReverseProxy = reverseProxyConfig
|
||||
}
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// FindEnabledGroupIdWithReverseProxyId 查找包含某个反向代理的服务分组
|
||||
func (this *ServerGroupDAO) FindEnabledGroupIdWithReverseProxyId(tx *dbs.Tx, reverseProxyId int64) (serverId int64, err error) {
|
||||
return this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Where("(JSON_CONTAINS(httpReverseProxy, :jsonQuery) OR JSON_CONTAINS(tcpReverseProxy, :jsonQuery) OR JSON_CONTAINS(udpReverseProxy, :jsonQuery))").
|
||||
Param("jsonQuery", maps.Map{"reverseProxyId": reverseProxyId}.AsJSON()).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, serverId := range serverIds {
|
||||
err = SharedServerDAO.NotifyUpdate(tx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
package models
|
||||
|
||||
// 服务分组
|
||||
// ServerGroup 服务分组
|
||||
type ServerGroup struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Name string `field:"name"` // 名称
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
HttpReverseProxy string `field:"httpReverseProxy"` // 反向代理设置
|
||||
TcpReverseProxy string `field:"tcpReverseProxy"` // TCP反向代理
|
||||
UdpReverseProxy string `field:"udpReverseProxy"` // UDP反向代理
|
||||
WebId uint32 `field:"webId"` // Web配置ID
|
||||
}
|
||||
|
||||
type ServerGroupOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
Name interface{} // 名称
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
HttpReverseProxy interface{} // 反向代理设置
|
||||
TcpReverseProxy interface{} // TCP反向代理
|
||||
UdpReverseProxy interface{} // UDP反向代理
|
||||
WebId interface{} // Web配置ID
|
||||
}
|
||||
|
||||
func NewServerGroupOperator() *ServerGroupOperator {
|
||||
|
||||
@@ -1 +1,21 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
)
|
||||
|
||||
// DecodeGroupIds 解析服务所属分组ID
|
||||
func (this *Server) DecodeGroupIds() []int64 {
|
||||
if len(this.GroupIds) == 0 {
|
||||
return []int64{}
|
||||
}
|
||||
|
||||
var result = []int64{}
|
||||
err := json.Unmarshal([]byte(this.GroupIds), &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("Server.DecodeGroupIds", err.Error())
|
||||
// 忽略错误
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@ import (
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -48,12 +52,40 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// PartitionTable 获取分区表格名称
|
||||
func (this *ServerDomainHourlyStatDAO) PartitionTable(domain string) string {
|
||||
if len(domain) == 0 {
|
||||
return this.Table + "_0"
|
||||
}
|
||||
if (domain[0] >= '0' && domain[0] <= '9') || (domain[0] >= 'a' && domain[0] <= 'z') || (domain[0] >= 'A' && domain[0] <= 'Z') {
|
||||
return this.Table + "_" + strings.ToLower(string(domain[0]))
|
||||
}
|
||||
|
||||
return this.Table + "_0"
|
||||
}
|
||||
|
||||
// FindAllPartitionTables 获取所有表格名称
|
||||
func (this *ServerDomainHourlyStatDAO) FindAllPartitionTables() []string {
|
||||
var tables = []string{}
|
||||
for i := '0'; i <= '9'; i++ {
|
||||
tables = append(tables, this.Table+"_"+string(i))
|
||||
}
|
||||
for i := 'a'; i <= 'z'; i++ {
|
||||
tables = append(tables, this.Table+"_"+string(i))
|
||||
}
|
||||
return tables
|
||||
}
|
||||
|
||||
// IncreaseHourlyStat 增加统计数据
|
||||
func (this *ServerDomainHourlyStatDAO) IncreaseHourlyStat(tx *dbs.Tx, clusterId int64, nodeId int64, serverId int64, domain string, hour string, bytes int64, cachedBytes int64, countRequests int64, countCachedRequests int64, countAttackRequests int64, attackBytes int64) error {
|
||||
if len(hour) != 10 {
|
||||
return errors.New("invalid hour '" + hour + "'")
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
return nil
|
||||
}
|
||||
err := this.Query(tx).
|
||||
Table(this.PartitionTable(domain)).
|
||||
Param("bytes", bytes).
|
||||
Param("cachedBytes", cachedBytes).
|
||||
Param("countRequests", countRequests).
|
||||
@@ -87,69 +119,212 @@ func (this *ServerDomainHourlyStatDAO) IncreaseHourlyStat(tx *dbs.Tx, clusterId
|
||||
}
|
||||
|
||||
// FindTopDomainStats 取得一定时间内的域名排行数据
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStats(tx *dbs.Tx, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, err error) {
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err = this.Query(tx).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStats(tx *dbs.Tx, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, resultErr error) {
|
||||
var tables = this.FindAllPartitionTables()
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(tables))
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
for _, table := range tables {
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
var topResults = []*ServerDomainHourlyStat{}
|
||||
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&topResults).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
return
|
||||
}
|
||||
|
||||
if len(topResults) > 0 {
|
||||
locker.Lock()
|
||||
result = append(result, topResults...)
|
||||
locker.Unlock()
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].CountRequests > result[j].CountRequests
|
||||
})
|
||||
|
||||
if len(result) > types.Int(size) {
|
||||
result = result[:types.Int(size)]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindTopDomainStatsWithClusterId 取得集群上的一定时间内的域名排行数据
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithClusterId(tx *dbs.Tx, clusterId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, err error) {
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithClusterId(tx *dbs.Tx, clusterId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, resultErr error) {
|
||||
var tables = this.FindAllPartitionTables()
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(tables))
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
for _, table := range tables {
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
var topResults = []*ServerDomainHourlyStat{}
|
||||
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Attr("clusterId", clusterId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
UseIndex("hour").
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&topResults).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
return
|
||||
}
|
||||
|
||||
if len(topResults) > 0 {
|
||||
locker.Lock()
|
||||
result = append(result, topResults...)
|
||||
locker.Unlock()
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].CountRequests > result[j].CountRequests
|
||||
})
|
||||
|
||||
if len(result) > types.Int(size) {
|
||||
result = result[:types.Int(size)]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindTopDomainStatsWithNodeId 取得节点上的一定时间内的域名排行数据
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithNodeId(tx *dbs.Tx, nodeId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, err error) {
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err = this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithNodeId(tx *dbs.Tx, nodeId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, resultErr error) {
|
||||
var tables = this.FindAllPartitionTables()
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(tables))
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
for _, table := range tables {
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
var topResults = []*ServerDomainHourlyStat{}
|
||||
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Attr("nodeId", nodeId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
UseIndex("hour").
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&topResults).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
return
|
||||
}
|
||||
|
||||
if len(topResults) > 0 {
|
||||
locker.Lock()
|
||||
result = append(result, topResults...)
|
||||
locker.Unlock()
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].CountRequests > result[j].CountRequests
|
||||
})
|
||||
|
||||
if len(result) > types.Int(size) {
|
||||
result = result[:types.Int(size)]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindTopDomainStatsWithServerId 取得某个服务的一定时间内的域名排行数据
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithServerId(tx *dbs.Tx, serverId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, err error) {
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err = this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithServerId(tx *dbs.Tx, serverId int64, hourFrom string, hourTo string, size int64) (result []*ServerDomainHourlyStat, resultErr error) {
|
||||
var tables = this.FindAllPartitionTables()
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(tables))
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
for _, table := range tables {
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
var topResults = []*ServerDomainHourlyStat{}
|
||||
|
||||
// TODO 节点如果已经被删除,则忽略
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Attr("serverId", serverId).
|
||||
Between("hour", hourFrom, hourTo).
|
||||
UseIndex("hour").
|
||||
Result("domain, MIN(serverId) AS serverId, SUM(bytes) AS bytes, SUM(cachedBytes) AS cachedBytes, SUM(countRequests) AS countRequests, SUM(countCachedRequests) AS countCachedRequests, SUM(countAttackRequests) AS countAttackRequests, SUM(attackBytes) AS attackBytes").
|
||||
Group("domain").
|
||||
Desc("countRequests").
|
||||
Limit(size).
|
||||
Slice(&topResults).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
return
|
||||
}
|
||||
|
||||
if len(topResults) > 0 {
|
||||
locker.Lock()
|
||||
result = append(result, topResults...)
|
||||
locker.Unlock()
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].CountRequests > result[j].CountRequests
|
||||
})
|
||||
|
||||
if len(result) > types.Int(size) {
|
||||
result = result[:types.Int(size)]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
for _, table := range this.FindAllPartitionTables() {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,77 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServerDomainHourlyStatDAO_PartitionTable(t *testing.T) {
|
||||
var a = assert.NewAssertion(t)
|
||||
|
||||
var dao = NewServerDomainHourlyStatDAO()
|
||||
a.IsTrue(dao.PartitionTable("") == "edgeServerDomainHourlyStats_0")
|
||||
a.IsTrue(dao.PartitionTable("a1") == "edgeServerDomainHourlyStats_a")
|
||||
a.IsTrue(dao.PartitionTable("Y1") == "edgeServerDomainHourlyStats_y")
|
||||
a.IsTrue(dao.PartitionTable("z1") == "edgeServerDomainHourlyStats_z")
|
||||
a.IsTrue(dao.PartitionTable("A1") == "edgeServerDomainHourlyStats_a")
|
||||
a.IsTrue(dao.PartitionTable("Z1") == "edgeServerDomainHourlyStats_z")
|
||||
a.IsTrue(dao.PartitionTable("中国") == "edgeServerDomainHourlyStats_0")
|
||||
a.IsTrue(dao.PartitionTable("_") == "edgeServerDomainHourlyStats_0")
|
||||
a.IsTrue(dao.PartitionTable(" ") == "edgeServerDomainHourlyStats_0")
|
||||
}
|
||||
|
||||
func TestServerDomainHourlyStatDAO_FindAllPartitionTables(t *testing.T) {
|
||||
var dao = NewServerDomainHourlyStatDAO()
|
||||
t.Log(dao.FindAllPartitionTables())
|
||||
}
|
||||
|
||||
func TestServerDomainHourlyStatDAO_IncreaseHourlyStat(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
for i := 0; i < 1_000_000; i++ {
|
||||
var f = string([]rune{int32(rands.Int('0', '9'))})
|
||||
if i % 30 > 0 {
|
||||
f = string([]rune{int32(rands.Int('a', 'z'))})
|
||||
}
|
||||
|
||||
err := NewServerDomainHourlyStatDAO().IncreaseHourlyStat(nil, 18, 48, 23, f+"rand"+types.String(i%500_000)+".com", timeutil.Format("Ymd")+fmt.Sprintf("%02d", rands.Int(0, 23)), 1, 1, 1, 1, 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i%10000 == 0 {
|
||||
t.Log(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDomainHourlyStatDAO_FindTopDomainStats(t *testing.T) {
|
||||
var dao = NewServerDomainHourlyStatDAO()
|
||||
var before = time.Now()
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
stats, err := dao.FindTopDomainStats(nil, timeutil.Format("Ymd00"), timeutil.Format("Ymd23"), 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, stat := range stats {
|
||||
t.Log(stat.Domain, stat.CountRequests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDomainHourlyStatDAO_Clean(t *testing.T) {
|
||||
var dao = NewServerDomainHourlyStatDAO()
|
||||
err := dao.Clean(nil, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ func TestTrafficHourlyStatDAO_IncreaseDayBytes(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
now := time.Now()
|
||||
err := SharedTrafficHourlyStatDAO.IncreaseHourlyBytes(nil, timeutil.Format("YmdH"), 1)
|
||||
err := SharedTrafficHourlyStatDAO.IncreaseHourlyStat(nil, timeutil.Format("YmdH"), 1, 1, 1, 1, 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 设置配置
|
||||
// UpdateSetting 设置配置
|
||||
func (this *SysSettingDAO) UpdateSetting(tx *dbs.Tx, codeFormat string, valueJSON []byte, codeFormatArgs ...interface{}) error {
|
||||
if len(codeFormatArgs) > 0 {
|
||||
codeFormat = fmt.Sprintf(codeFormat, codeFormatArgs...)
|
||||
@@ -77,7 +77,7 @@ func (this *SysSettingDAO) UpdateSetting(tx *dbs.Tx, codeFormat string, valueJSO
|
||||
return lastErr
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
// ReadSetting 读取配置
|
||||
func (this *SysSettingDAO) ReadSetting(tx *dbs.Tx, code string, codeFormatArgs ...interface{}) (valueJSON []byte, err error) {
|
||||
if len(codeFormatArgs) > 0 {
|
||||
code = fmt.Sprintf(code, codeFormatArgs...)
|
||||
@@ -89,7 +89,7 @@ func (this *SysSettingDAO) ReadSetting(tx *dbs.Tx, code string, codeFormatArgs .
|
||||
return []byte(col), err
|
||||
}
|
||||
|
||||
// 对比配置中的数字大小
|
||||
// CompareInt64Setting 对比配置中的数字大小
|
||||
func (this *SysSettingDAO) CompareInt64Setting(tx *dbs.Tx, code string, anotherValue int64) (int8, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, code)
|
||||
if err != nil {
|
||||
@@ -105,7 +105,7 @@ func (this *SysSettingDAO) CompareInt64Setting(tx *dbs.Tx, code string, anotherV
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// 读取全局配置
|
||||
// ReadGlobalConfig 读取全局配置
|
||||
func (this *SysSettingDAO) ReadGlobalConfig(tx *dbs.Tx) (*serverconfigs.GlobalConfig, error) {
|
||||
globalConfigData, err := this.ReadSetting(tx, systemconfigs.SettingCodeServerGlobalConfig)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,4 +15,5 @@ type Record struct {
|
||||
Type RecordType `json:"type"`
|
||||
Value string `json:"value"`
|
||||
Route string `json:"route"`
|
||||
TTL int32 `json:"ttl"`
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -87,6 +88,7 @@ func (this *AliDNSProvider) GetRecords(domain string) (records []*dnstypes.Recor
|
||||
Type: record.Type,
|
||||
Value: record.Value,
|
||||
Route: record.Line,
|
||||
TTL: types.Int32(record.TTL),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -141,6 +143,10 @@ func (this *AliDNSProvider) AddRecord(domain string, newRecord *dnstypes.Record)
|
||||
req.DomainName = domain
|
||||
req.Line = newRecord.Route
|
||||
|
||||
if newRecord.TTL > 0 {
|
||||
req.TTL = requests.NewInteger(types.Int(newRecord.TTL))
|
||||
}
|
||||
|
||||
resp := alidns.CreateAddDomainRecordResponse()
|
||||
err := this.doAPI(req, resp)
|
||||
if err != nil {
|
||||
@@ -162,6 +168,10 @@ func (this *AliDNSProvider) UpdateRecord(domain string, record *dnstypes.Record,
|
||||
req.Value = newRecord.Value
|
||||
req.Line = newRecord.Route
|
||||
|
||||
if newRecord.TTL > 0 {
|
||||
req.TTL = requests.NewInteger(types.Int(newRecord.TTL))
|
||||
}
|
||||
|
||||
resp := alidns.CreateUpdateDomainRecordResponse()
|
||||
err := this.doAPI(req, resp)
|
||||
return err
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@@ -158,6 +159,7 @@ func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordTy
|
||||
Name: record.Name,
|
||||
Type: record.Type,
|
||||
Value: record.Content,
|
||||
TTL: types.Int32(record.Ttl),
|
||||
Route: CloudFlareDefaultRoute,
|
||||
}, nil
|
||||
}
|
||||
@@ -170,11 +172,17 @@ func (this *CloudFlareProvider) AddRecord(domain string, newRecord *dnstypes.Rec
|
||||
}
|
||||
|
||||
resp := new(cloudflare.CreateDNSRecordResponse)
|
||||
|
||||
var ttl = newRecord.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 1 // 自动默认
|
||||
}
|
||||
|
||||
err = this.doAPI(http.MethodPost, "zones/"+zoneId+"/dns_records", nil, maps.Map{
|
||||
"type": newRecord.Type,
|
||||
"name": newRecord.Name + "." + domain,
|
||||
"content": newRecord.Value,
|
||||
"ttl": 1,
|
||||
"ttl": ttl,
|
||||
}, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -189,12 +197,17 @@ func (this *CloudFlareProvider) UpdateRecord(domain string, record *dnstypes.Rec
|
||||
return err
|
||||
}
|
||||
|
||||
var ttl = newRecord.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 1 // 自动默认
|
||||
}
|
||||
|
||||
resp := new(cloudflare.UpdateDNSRecordResponse)
|
||||
return this.doAPI(http.MethodPut, "zones/"+zoneId+"/dns_records/"+record.Id, nil, maps.Map{
|
||||
"type": newRecord.Type,
|
||||
"name": newRecord.Name + "." + domain,
|
||||
"content": newRecord.Value,
|
||||
"ttl": 1,
|
||||
"ttl": ttl,
|
||||
}, resp)
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ func TestCloudFlareProvider_AddRecord(t *testing.T) {
|
||||
Type: dnstypes.RecordTypeA,
|
||||
Value: "182.92.212.46",
|
||||
Route: "",
|
||||
TTL: 300,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -13,6 +13,10 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
DNSPodMaxTTL int32 = 604800
|
||||
)
|
||||
|
||||
// DNSPodProvider DNSPod服务商
|
||||
type DNSPodProvider struct {
|
||||
BaseProvider
|
||||
@@ -94,6 +98,7 @@ func (this *DNSPodProvider) GetRecords(domain string) (records []*dnstypes.Recor
|
||||
Type: recordMap.GetString("type"),
|
||||
Value: recordMap.GetString("value"),
|
||||
Route: recordMap.GetString("line"),
|
||||
TTL: recordMap.GetInt32("ttl"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -165,13 +170,18 @@ func (this *DNSPodProvider) AddRecord(domain string, newRecord *dnstypes.Record)
|
||||
if newRecord.Type == dnstypes.RecordTypeCNAME && !strings.HasSuffix(newRecord.Value, ".") {
|
||||
newRecord.Value += "."
|
||||
}
|
||||
_, err := this.post("/Record.Create", map[string]string{
|
||||
|
||||
var args = map[string]string{
|
||||
"domain": domain,
|
||||
"sub_domain": newRecord.Name,
|
||||
"record_type": newRecord.Type,
|
||||
"value": newRecord.Value,
|
||||
"record_line": newRecord.Route,
|
||||
})
|
||||
}
|
||||
if newRecord.TTL > 0 && newRecord.TTL <= DNSPodMaxTTL {
|
||||
args["ttl"] = types.String(newRecord.TTL)
|
||||
}
|
||||
_, err := this.post("/Record.Create", args)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -188,14 +198,19 @@ func (this *DNSPodProvider) UpdateRecord(domain string, record *dnstypes.Record,
|
||||
if newRecord.Type == dnstypes.RecordTypeCNAME && !strings.HasSuffix(newRecord.Value, ".") {
|
||||
newRecord.Value += "."
|
||||
}
|
||||
_, err := this.post("/Record.Modify", map[string]string{
|
||||
|
||||
var args = map[string]string{
|
||||
"domain": domain,
|
||||
"record_id": record.Id,
|
||||
"sub_domain": newRecord.Name,
|
||||
"record_type": newRecord.Type,
|
||||
"value": newRecord.Value,
|
||||
"record_line": newRecord.Route,
|
||||
})
|
||||
}
|
||||
if newRecord.TTL > 0 && newRecord.TTL <= DNSPodMaxTTL {
|
||||
args["ttl"] = types.String(newRecord.TTL)
|
||||
}
|
||||
_, err := this.post("/Record.Modify", args)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ func TestDNSPodProvider_AddRecord(t *testing.T) {
|
||||
Name: "hello-forward",
|
||||
Value: "hello.yun4s.cn",
|
||||
Route: "联通",
|
||||
TTL: 300,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -35,6 +35,8 @@ var huaweiDNSHTTPClient = &http.Client{
|
||||
},
|
||||
}
|
||||
|
||||
// HuaweiDNSProvider 华为云DNS
|
||||
// 相关文档链接:https://support.huaweicloud.com/api-dns/dns_api_62001.html
|
||||
type HuaweiDNSProvider struct {
|
||||
BaseProvider
|
||||
|
||||
@@ -100,6 +102,7 @@ func (this *HuaweiDNSProvider) GetRecords(domain string) (records []*dnstypes.Re
|
||||
Type: recordSet.Type,
|
||||
Value: value,
|
||||
Route: recordSet.Line,
|
||||
TTL: types.Int32(recordSet.Ttl),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1320,6 +1323,7 @@ func (this *HuaweiDNSProvider) QueryRecord(domain string, name string, recordTyp
|
||||
Type: recordType,
|
||||
Value: recordSet.Records[0],
|
||||
Route: recordSet.Line,
|
||||
TTL: types.Int32(recordSet.Ttl),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1331,12 +1335,17 @@ func (this *HuaweiDNSProvider) AddRecord(domain string, newRecord *dnstypes.Reco
|
||||
}
|
||||
|
||||
var resp = new(huaweidns.ZonesCreateRecordSetResponse)
|
||||
var ttl = newRecord.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 300
|
||||
}
|
||||
err = this.doAPI(http.MethodPost, "/v2.1/zones/"+zoneId+"/recordsets", map[string]string{}, maps.Map{
|
||||
"name": newRecord.Name + "." + domain + ".",
|
||||
"description": "CDN系统自动创建",
|
||||
"type": newRecord.Type,
|
||||
"records": []string{newRecord.Value},
|
||||
"line": newRecord.Route,
|
||||
"ttl": ttl,
|
||||
}, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1362,6 +1371,11 @@ func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Reco
|
||||
recordId = record.Id
|
||||
}
|
||||
|
||||
var ttl = newRecord.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 300
|
||||
}
|
||||
|
||||
var resp = new(huaweidns.ZonesUpdateRecordSetResponse)
|
||||
err = this.doAPI(http.MethodPut, "/v2.1/zones/"+zoneId+"/recordsets/"+recordId, map[string]string{}, maps.Map{
|
||||
"name": newRecord.Name + "." + domain + ".",
|
||||
@@ -1369,6 +1383,7 @@ func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Reco
|
||||
"type": newRecord.Type,
|
||||
"records": []string{newRecord.Value},
|
||||
"line": newRecord.Route, // TODO 华为云此API无法修改线路,API地址:https://support.huaweicloud.com/api-dns/dns_api_65006.html
|
||||
"ttl": ttl,
|
||||
}, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -71,6 +71,7 @@ func TestHuaweiDNSProvider_AddRecord(t *testing.T) {
|
||||
Type: "A",
|
||||
Value: "192.168.2.40",
|
||||
Route: "Beijing",
|
||||
TTL: 120,
|
||||
}
|
||||
err = provider.AddRecord("yun4s.cn", record)
|
||||
if err != nil {
|
||||
|
||||
@@ -83,6 +83,7 @@ func (this *LocalEdgeDNSProvider) GetRecords(domain string) (records []*dnstypes
|
||||
Type: record.Type,
|
||||
Value: record.Value,
|
||||
Route: routeIds[0],
|
||||
TTL: types.Int32(record.Ttl),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -183,6 +184,7 @@ func (this *LocalEdgeDNSProvider) QueryRecord(domain string, name string, record
|
||||
Type: record.Type,
|
||||
Value: record.Value,
|
||||
Route: routeIdString,
|
||||
TTL: types.Int32(record.Ttl),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -202,7 +204,10 @@ func (this *LocalEdgeDNSProvider) AddRecord(domain string, newRecord *dnstypes.R
|
||||
routeIds = append(routeIds, newRecord.Route)
|
||||
}
|
||||
|
||||
_, err = nameservers.SharedNSRecordDAO.CreateRecord(tx, domainId, "", newRecord.Name, newRecord.Type, newRecord.Value, this.ttl, routeIds)
|
||||
if newRecord.TTL <= 0 {
|
||||
newRecord.TTL = this.ttl
|
||||
}
|
||||
_, err = nameservers.SharedNSRecordDAO.CreateRecord(tx, domainId, "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -226,8 +231,12 @@ func (this *LocalEdgeDNSProvider) UpdateRecord(domain string, record *dnstypes.R
|
||||
routeIds = append(routeIds, newRecord.Route)
|
||||
}
|
||||
|
||||
if newRecord.TTL <= 0 {
|
||||
newRecord.TTL = this.ttl
|
||||
}
|
||||
|
||||
if len(record.Id) > 0 {
|
||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(record.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, this.ttl, routeIds, true)
|
||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(record.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -237,7 +246,7 @@ func (this *LocalEdgeDNSProvider) UpdateRecord(domain string, record *dnstypes.R
|
||||
return err
|
||||
}
|
||||
if realRecord != nil {
|
||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(realRecord.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, this.ttl, routeIds, true)
|
||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(realRecord.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ func TestLocalEdgeDNSProvider_AddRecord(t *testing.T) {
|
||||
Type: dnstypes.RecordTypeA,
|
||||
Value: "10.0.0.1",
|
||||
Route: "id:7",
|
||||
TTL: 300,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -53,6 +53,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterNodeIPAddressLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressThresholdService{}).(*services.NodeIPAddressThresholdService)
|
||||
pb.RegisterNodeIPAddressThresholdServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APINodeService{}).(*services.APINodeService)
|
||||
pb.RegisterAPINodeServiceServer(server, instance)
|
||||
|
||||
@@ -156,7 +156,7 @@ func (this *NSNodeService) NsNodeStream(server pb.NSNodeService_NsNodeStreamServ
|
||||
}
|
||||
subject := "DNS节点\"" + nodeName + "\"已经恢复在线"
|
||||
msg := "DNS节点\"" + nodeName + "\"已经恢复在线"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, models.MessageTypeNSNodeActive, models.MessageLevelSuccess, subject, msg, nil)
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, models.MessageTypeNSNodeActive, models.MessageLevelSuccess, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
})
|
||||
}
|
||||
|
||||
// 是否是企业版
|
||||
// 是否是商业版
|
||||
isPlus, err := authority.SharedAuthorityKeyDAO.IsPlus(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -657,20 +657,31 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
result.NsNodeUpgradeInfo = upgradeInfo
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
// Report节点升级信息
|
||||
if isPlus {
|
||||
topDomainStats, err := stats.SharedServerDomainHourlyStatDAO.FindTopDomainStats(tx, hourFrom, hourTo, 10)
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.ReportNodeVersion,
|
||||
}
|
||||
countNodes, err := models.SharedReportNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range topDomainStats {
|
||||
result.TopDomainStats = append(result.TopDomainStats, &pb.ComposeAdminDashboardResponse_DomainStat{
|
||||
ServerId: int64(stat.ServerId),
|
||||
Domain: stat.Domain,
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
Bytes: int64(stat.Bytes),
|
||||
})
|
||||
}
|
||||
upgradeInfo.CountNodes = countNodes
|
||||
result.ReportNodeUpgradeInfo = upgradeInfo
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
topDomainStats, err := stats.SharedServerDomainHourlyStatDAO.FindTopDomainStats(tx, hourFrom, hourTo, 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range topDomainStats {
|
||||
result.TopDomainStats = append(result.TopDomainStats, &pb.ComposeAdminDashboardResponse_DomainStat{
|
||||
ServerId: int64(stat.ServerId),
|
||||
Domain: stat.Domain,
|
||||
CountRequests: int64(stat.CountRequests),
|
||||
Bytes: int64(stat.Bytes),
|
||||
})
|
||||
}
|
||||
|
||||
// 节点排行
|
||||
|
||||
@@ -402,6 +402,19 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 自动设置的cname记录
|
||||
var cnameRecords = []string{}
|
||||
var ttl int32
|
||||
if len(cluster.Dns) > 0 {
|
||||
dnsConfig, _ := cluster.DecodeDNSConfig()
|
||||
if dnsConfig != nil {
|
||||
cnameRecords = dnsConfig.CNameRecords
|
||||
if dnsConfig.TTL > 0 {
|
||||
ttl = dnsConfig.TTL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 节点域名
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId, true)
|
||||
if err != nil {
|
||||
@@ -441,7 +454,7 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
}
|
||||
for _, route := range routeCodes {
|
||||
for _, ipAddress := range ipAddresses {
|
||||
ip := ipAddress.Ip
|
||||
ip := ipAddress.DNSIP()
|
||||
if len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -464,6 +477,7 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
Type: recordType,
|
||||
Value: ip,
|
||||
Route: route,
|
||||
TTL: ttl,
|
||||
},
|
||||
})
|
||||
nodesChanged = true
|
||||
@@ -520,6 +534,29 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
doneServerRecords = append(doneServerRecords, record)
|
||||
}
|
||||
}
|
||||
|
||||
// 自动设置的CNAME
|
||||
for _, cnameRecord := range cnameRecords {
|
||||
serverDNSNames = append(serverDNSNames, cnameRecord)
|
||||
record, ok := serverRecordsMap[cnameRecord]
|
||||
if !ok {
|
||||
serversChanged = true
|
||||
result = append(result, maps.Map{
|
||||
"action": "create",
|
||||
"record": &dnstypes.Record{
|
||||
Id: "",
|
||||
Name: cnameRecord,
|
||||
Type: dnstypes.RecordTypeCNAME,
|
||||
Value: clusterDomain + ".",
|
||||
Route: "", // 注意这里为空,需要在执行过程中获取默认值
|
||||
TTL: ttl,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// DNS同步相关任务
|
||||
// DNSTaskService DNS同步相关任务
|
||||
type DNSTaskService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// 检查是否有正在执行的任务
|
||||
// ExistsDNSTasks 检查是否有正在执行的任务
|
||||
func (this *DNSTaskService) ExistsDNSTasks(ctx context.Context, req *pb.ExistsDNSTasksRequest) (*pb.ExistsDNSTasksResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -37,7 +37,7 @@ func (this *DNSTaskService) ExistsDNSTasks(ctx context.Context, req *pb.ExistsDN
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 查找正在执行的所有任务
|
||||
// FindAllDoingDNSTasks 查找正在执行的所有任务
|
||||
func (this *DNSTaskService) FindAllDoingDNSTasks(ctx context.Context, req *pb.FindAllDoingDNSTasksRequest) (*pb.FindAllDoingDNSTasksResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -45,7 +45,7 @@ func (this *DNSTaskService) FindAllDoingDNSTasks(ctx context.Context, req *pb.Fi
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
tasks, err := dns.SharedDNSTaskDAO.FindAllDoingOrErrorTasks(tx)
|
||||
tasks, err := dns.SharedDNSTaskDAO.FindAllDoingOrErrorTasks(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (this *DNSTaskService) FindAllDoingDNSTasks(ctx context.Context, req *pb.Fi
|
||||
return &pb.FindAllDoingDNSTasksResponse{DnsTasks: pbTasks}, nil
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
// DeleteDNSTask 删除任务
|
||||
func (this *DNSTaskService) DeleteDNSTask(ctx context.Context, req *pb.DeleteDNSTaskRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
|
||||
@@ -409,79 +409,11 @@ func (this *NodeService) UpdateNode(ctx context.Context, req *pb.UpdateNodeReque
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
var maxCacheDiskCapacityJSON []byte
|
||||
if req.MaxCacheDiskCapacity != nil {
|
||||
maxCacheDiskCapacityJSON, err = json.Marshal(&shared.SizeCapacity{
|
||||
Count: req.MaxCacheDiskCapacity.Count,
|
||||
Unit: req.MaxCacheDiskCapacity.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var maxCacheMemoryCapacityJSON []byte
|
||||
if req.MaxCacheMemoryCapacity != nil {
|
||||
maxCacheMemoryCapacityJSON, err = json.Marshal(&shared.SizeCapacity{
|
||||
Count: req.MaxCacheMemoryCapacity.Count,
|
||||
Unit: req.MaxCacheMemoryCapacity.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.SecondaryNodeClusterIds, req.NodeGroupId, req.NodeRegionId, req.MaxCPU, req.IsOn, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON)
|
||||
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.SecondaryNodeClusterIds, req.NodeGroupId, req.NodeRegionId, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 登录信息
|
||||
if req.NodeLogin == nil {
|
||||
err = models.SharedNodeLoginDAO.DisableNodeLogins(tx, nodeconfigs.NodeRoleNode, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if req.NodeLogin.Id > 0 {
|
||||
err = models.SharedNodeLoginDAO.UpdateNodeLogin(tx, req.NodeLogin.Id, req.NodeLogin.Name, req.NodeLogin.Type, req.NodeLogin.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
_, err = models.SharedNodeLoginDAO.CreateNodeLogin(tx, nodeconfigs.NodeRoleNode, req.NodeId, req.NodeLogin.Name, req.NodeLogin.Type, req.NodeLogin.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存DNS相关
|
||||
nodeDNS, err := models.SharedNodeDAO.FindEnabledNodeDNS(tx, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nodeDNS != nil {
|
||||
var routesMap = nodeDNS.DNSRouteCodes()
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.DnsRoutes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routesMap[domainId] = codes
|
||||
}
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, req.NodeId, routesMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -1262,7 +1194,7 @@ func (this *NodeService) FindAllEnabledNodesDNSWithNodeClusterId(ctx context.Con
|
||||
}
|
||||
|
||||
for _, ipAddress := range ipAddresses {
|
||||
ip := ipAddress.Ip
|
||||
ip := ipAddress.DNSIP()
|
||||
if len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -1377,22 +1309,43 @@ func (this *NodeService) UpdateNodeDNS(ctx context.Context, req *pb.UpdateNodeDN
|
||||
}
|
||||
|
||||
routeCodeMap := node.DNSRouteCodes()
|
||||
if req.DnsDomainId > 0 && len(req.Routes) > 0 {
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.Routes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
if req.DnsDomainId > 0 {
|
||||
if len(req.Routes) > 0 {
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.Routes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routeCodeMap[domainId] = codes
|
||||
for domainId, codes := range m {
|
||||
routeCodeMap[domainId] = codes
|
||||
}
|
||||
} else {
|
||||
delete(routeCodeMap, req.DnsDomainId)
|
||||
}
|
||||
} else {
|
||||
delete(routeCodeMap, req.DnsDomainId)
|
||||
if len(req.Routes) > 0 {
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.Routes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routeCodeMap[domainId] = codes
|
||||
}
|
||||
} else {
|
||||
// 清空
|
||||
routeCodeMap = map[int64][]string{}
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, req.NodeId, routeCodeMap)
|
||||
@@ -1412,7 +1365,7 @@ func (this *NodeService) UpdateNodeDNS(ctx context.Context, req *pb.UpdateNodeDN
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
_, err = models.SharedNodeIPAddressDAO.CreateAddress(tx, adminId, req.NodeId, nodeconfigs.NodeRoleNode, "DNS IP", req.IpAddr, true, nil)
|
||||
_, err = models.SharedNodeIPAddressDAO.CreateAddress(tx, adminId, req.NodeId, nodeconfigs.NodeRoleNode, "DNS IP", req.IpAddr, true, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1532,3 +1485,57 @@ func (this *NodeService) DownloadNodeInstallationFile(ctx context.Context, req *
|
||||
Filename: filepath.Base(file.Path),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeSystem 修改节点系统信息
|
||||
func (this *NodeService) UpdateNodeSystem(ctx context.Context, req *pb.UpdateNodeSystemRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeDAO.UpdateNodeSystem(tx, req.NodeId, req.MaxCPU)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateNodeCache 修改节点缓存设置
|
||||
func (this *NodeService) UpdateNodeCache(ctx context.Context, req *pb.UpdateNodeCacheRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
var maxCacheDiskCapacityJSON []byte
|
||||
if req.MaxCacheDiskCapacity != nil {
|
||||
maxCacheDiskCapacityJSON, err = json.Marshal(&shared.SizeCapacity{
|
||||
Count: req.MaxCacheDiskCapacity.Count,
|
||||
Unit: req.MaxCacheDiskCapacity.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var maxCacheMemoryCapacityJSON []byte
|
||||
if req.MaxCacheMemoryCapacity != nil {
|
||||
maxCacheMemoryCapacityJSON, err = json.Marshal(&shared.SizeCapacity{
|
||||
Count: req.MaxCacheMemoryCapacity.Count,
|
||||
Unit: req.MaxCacheMemoryCapacity.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNodeCache(tx, req.NodeId, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -446,6 +446,8 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
Provider: nil,
|
||||
NodesAutoSync: dnsConfig.NodesAutoSync,
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -502,6 +504,8 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
Provider: pbProvider,
|
||||
NodesAutoSync: dnsConfig.NodesAutoSync,
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
DefaultRoute: defaultRoute,
|
||||
}, nil
|
||||
}
|
||||
@@ -595,7 +599,7 @@ func (this *NodeClusterService) UpdateNodeClusterDNS(ctx context.Context, req *p
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync)
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync, req.CnameRecords, req.Ttl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func (this *NodeIPAddressService) CreateNodeIPAddress(ctx context.Context, req *
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
addressId, err := models.SharedNodeIPAddressDAO.CreateAddress(tx, adminId, req.NodeId, req.Role, req.Name, req.Ip, req.CanAccess, req.ThresholdsJSON)
|
||||
addressId, err := models.SharedNodeIPAddressDAO.CreateAddress(tx, adminId, req.NodeId, req.Role, req.Name, req.Ip, req.CanAccess, req.IsUp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func (this *NodeIPAddressService) UpdateNodeIPAddress(ctx context.Context, req *
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
err = models.SharedNodeIPAddressDAO.UpdateAddress(tx, adminId, req.NodeIPAddressId, req.Name, req.Ip, req.CanAccess, req.IsOn, req.ThresholdsJSON)
|
||||
err = models.SharedNodeIPAddressDAO.UpdateAddress(tx, adminId, req.NodeIPAddressId, req.Name, req.Ip, req.CanAccess, req.IsOn, req.IsUp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -83,8 +83,8 @@ func (this *NodeIPAddressService) DisableNodeIPAddress(ctx context.Context, req
|
||||
return &pb.DisableNodeIPAddressResponse{}, nil
|
||||
}
|
||||
|
||||
// DisableAllIPAddressesWithNodeId 禁用某个节点的IP地址
|
||||
func (this *NodeIPAddressService) DisableAllIPAddressesWithNodeId(ctx context.Context, req *pb.DisableAllIPAddressesWithNodeIdRequest) (*pb.DisableAllIPAddressesWithNodeIdResponse, error) {
|
||||
// DisableAllNodeIPAddressesWithNodeId 禁用某个节点的IP地址
|
||||
func (this *NodeIPAddressService) DisableAllNodeIPAddressesWithNodeId(ctx context.Context, req *pb.DisableAllNodeIPAddressesWithNodeIdRequest) (*pb.DisableAllNodeIPAddressesWithNodeIdResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -98,7 +98,7 @@ func (this *NodeIPAddressService) DisableAllIPAddressesWithNodeId(ctx context.Co
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.DisableAllIPAddressesWithNodeIdResponse{}, nil
|
||||
return &pb.DisableAllNodeIPAddressesWithNodeIdResponse{}, nil
|
||||
}
|
||||
|
||||
// FindEnabledNodeIPAddress 查找单个IP地址
|
||||
@@ -119,26 +119,26 @@ func (this *NodeIPAddressService) FindEnabledNodeIPAddress(ctx context.Context,
|
||||
var result *pb.NodeIPAddress = nil
|
||||
if address != nil {
|
||||
result = &pb.NodeIPAddress{
|
||||
Id: int64(address.Id),
|
||||
NodeId: int64(address.NodeId),
|
||||
Role: address.Role,
|
||||
Name: address.Name,
|
||||
Ip: address.Ip,
|
||||
Description: address.Description,
|
||||
State: int64(address.State),
|
||||
Order: int64(address.Order),
|
||||
CanAccess: address.CanAccess == 1,
|
||||
IsOn: address.IsOn == 1,
|
||||
IsUp: address.IsUp == 1,
|
||||
ThresholdsJSON: []byte(address.Thresholds),
|
||||
Id: int64(address.Id),
|
||||
NodeId: int64(address.NodeId),
|
||||
Role: address.Role,
|
||||
Name: address.Name,
|
||||
Ip: address.Ip,
|
||||
Description: address.Description,
|
||||
State: int64(address.State),
|
||||
Order: int64(address.Order),
|
||||
CanAccess: address.CanAccess == 1,
|
||||
IsOn: address.IsOn == 1,
|
||||
IsUp: address.IsUp == 1,
|
||||
BackupIP: address.DecodeBackupIP(),
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.FindEnabledNodeIPAddressResponse{NodeIPAddress: result}, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledIPAddressesWithNodeId 查找节点的所有地址
|
||||
func (this *NodeIPAddressService) FindAllEnabledIPAddressesWithNodeId(ctx context.Context, req *pb.FindAllEnabledIPAddressesWithNodeIdRequest) (*pb.FindAllEnabledIPAddressesWithNodeIdResponse, error) {
|
||||
// FindAllEnabledNodeIPAddressesWithNodeId 查找节点的所有地址
|
||||
func (this *NodeIPAddressService) FindAllEnabledNodeIPAddressesWithNodeId(ctx context.Context, req *pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest) (*pb.FindAllEnabledNodeIPAddressesWithNodeIdResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -155,26 +155,26 @@ func (this *NodeIPAddressService) FindAllEnabledIPAddressesWithNodeId(ctx contex
|
||||
result := []*pb.NodeIPAddress{}
|
||||
for _, address := range addresses {
|
||||
result = append(result, &pb.NodeIPAddress{
|
||||
Id: int64(address.Id),
|
||||
NodeId: int64(address.NodeId),
|
||||
Role: address.Role,
|
||||
Name: address.Name,
|
||||
Ip: address.Ip,
|
||||
Description: address.Description,
|
||||
State: int64(address.State),
|
||||
Order: int64(address.Order),
|
||||
CanAccess: address.CanAccess == 1,
|
||||
IsOn: address.IsOn == 1,
|
||||
IsUp: address.IsUp == 1,
|
||||
ThresholdsJSON: []byte(address.Thresholds),
|
||||
Id: int64(address.Id),
|
||||
NodeId: int64(address.NodeId),
|
||||
Role: address.Role,
|
||||
Name: address.Name,
|
||||
Ip: address.Ip,
|
||||
Description: address.Description,
|
||||
State: int64(address.State),
|
||||
Order: int64(address.Order),
|
||||
CanAccess: address.CanAccess == 1,
|
||||
IsOn: address.IsOn == 1,
|
||||
IsUp: address.IsUp == 1,
|
||||
BackupIP: address.DecodeBackupIP(),
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledIPAddressesWithNodeIdResponse{Addresses: result}, nil
|
||||
return &pb.FindAllEnabledNodeIPAddressesWithNodeIdResponse{NodeIPAddresses: result}, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledIPAddresses 计算IP地址数量
|
||||
func (this *NodeIPAddressService) CountAllEnabledIPAddresses(ctx context.Context, req *pb.CountAllEnabledIPAddressesRequest) (*pb.RPCCountResponse, error) {
|
||||
// CountAllEnabledNodeIPAddresses 计算IP地址数量
|
||||
func (this *NodeIPAddressService) CountAllEnabledNodeIPAddresses(ctx context.Context, req *pb.CountAllEnabledNodeIPAddressesRequest) (*pb.RPCCountResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -191,7 +191,7 @@ func (this *NodeIPAddressService) CountAllEnabledIPAddresses(ctx context.Context
|
||||
}
|
||||
|
||||
// ListEnabledIPAddresses 列出单页IP地址
|
||||
func (this *NodeIPAddressService) ListEnabledIPAddresses(ctx context.Context, req *pb.ListEnabledIPAddressesRequest) (*pb.ListEnabledIPAddressesResponse, error) {
|
||||
func (this *NodeIPAddressService) ListEnabledNodeIPAddresses(ctx context.Context, req *pb.ListEnabledNodeIPAddressesRequest) (*pb.ListEnabledNodeIPAddressesResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -207,17 +207,67 @@ func (this *NodeIPAddressService) ListEnabledIPAddresses(ctx context.Context, re
|
||||
var pbAddrs = []*pb.NodeIPAddress{}
|
||||
for _, addr := range addresses {
|
||||
pbAddrs = append(pbAddrs, &pb.NodeIPAddress{
|
||||
Id: int64(addr.Id),
|
||||
NodeId: int64(addr.NodeId),
|
||||
Role: addr.Role,
|
||||
Name: addr.Name,
|
||||
Ip: addr.Ip,
|
||||
Description: addr.Description,
|
||||
CanAccess: addr.CanAccess == 1,
|
||||
IsOn: addr.IsOn == 1,
|
||||
IsUp: addr.IsUp == 1,
|
||||
ThresholdsJSON: []byte(addr.Thresholds),
|
||||
Id: int64(addr.Id),
|
||||
NodeId: int64(addr.NodeId),
|
||||
Role: addr.Role,
|
||||
Name: addr.Name,
|
||||
Ip: addr.Ip,
|
||||
Description: addr.Description,
|
||||
CanAccess: addr.CanAccess == 1,
|
||||
IsOn: addr.IsOn == 1,
|
||||
IsUp: addr.IsUp == 1,
|
||||
BackupIP: addr.DecodeBackupIP(),
|
||||
})
|
||||
}
|
||||
return &pb.ListEnabledIPAddressesResponse{NodeIPAddresses: pbAddrs}, nil
|
||||
return &pb.ListEnabledNodeIPAddressesResponse{NodeIPAddresses: pbAddrs}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeIPAddressIsUp 设置上下线状态
|
||||
func (this *NodeIPAddressService) UpdateNodeIPAddressIsUp(ctx context.Context, req *pb.UpdateNodeIPAddressIsUpRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
adminId, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeIPAddressDAO.UpdateAddressIsUp(tx, req.NodeIPAddressId, req.IsUp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加日志
|
||||
if req.IsUp {
|
||||
err = models.SharedNodeIPAddressLogDAO.CreateLog(tx, adminId, req.NodeIPAddressId, "手动上线")
|
||||
} else {
|
||||
err = models.SharedNodeIPAddressLogDAO.CreateLog(tx, adminId, req.NodeIPAddressId, "手动下线")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// RestoreNodeIPAddressBackupIP 还原备用IP状态
|
||||
func (this *NodeIPAddressService) RestoreNodeIPAddressBackupIP(ctx context.Context, req *pb.RestoreNodeIPAddressBackupIPRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
adminId, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeIPAddressDAO.UpdateAddressBackupIP(tx, req.NodeIPAddressId, 0, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加日志
|
||||
err = models.SharedNodeIPAddressLogDAO.CreateLog(tx, adminId, req.NodeIPAddressId, "恢复IP状态")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ func (this *NodeIPAddressLogService) ListNodeIPAddressLogs(ctx context.Context,
|
||||
IsOn: log.IsOn == 1,
|
||||
IsUp: log.IsUp == 1,
|
||||
CanAccess: log.CanAccess == 1,
|
||||
BackupIP: log.BackupIP,
|
||||
NodeIPAddress: pbAddr,
|
||||
Admin: pbAdmin,
|
||||
})
|
||||
|
||||
171
internal/rpc/services/service_node_ip_address_threshold.go
Normal file
171
internal/rpc/services/service_node_ip_address_threshold.go
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// NodeIPAddressThresholdService IP阈值相关服务
|
||||
type NodeIPAddressThresholdService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateNodeIPAddressThreshold 创建阈值
|
||||
func (this *NodeIPAddressThresholdService) CreateNodeIPAddressThreshold(ctx context.Context, req *pb.CreateNodeIPAddressThresholdRequest) (*pb.CreateNodeIPAddressThresholdResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var items = []*nodeconfigs.IPAddressThresholdItemConfig{}
|
||||
if len(req.ItemsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ItemsJSON, &items)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode items failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var actions = []*nodeconfigs.IPAddressThresholdActionConfig{}
|
||||
if len(req.ActionsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ActionsJSON, &actions)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode actions failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
thresholdId, err := models.SharedNodeIPAddressThresholdDAO.CreateThreshold(tx, req.NodeIPAddressId, items, actions, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CreateNodeIPAddressThresholdResponse{NodeIPAddressThresholdId: thresholdId}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeIPAddressThreshold 修改阈值
|
||||
func (this *NodeIPAddressThresholdService) UpdateNodeIPAddressThreshold(ctx context.Context, req *pb.UpdateNodeIPAddressThresholdRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var items = []*nodeconfigs.IPAddressThresholdItemConfig{}
|
||||
if len(req.ItemsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ItemsJSON, &items)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode items failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var actions = []*nodeconfigs.IPAddressThresholdActionConfig{}
|
||||
if len(req.ActionsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ActionsJSON, &actions)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode actions failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
err = models.SharedNodeIPAddressThresholdDAO.UpdateThreshold(tx, req.NodeIPAddressThresholdId, items, actions, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteNodeIPAddressThreshold 删除阈值
|
||||
func (this *NodeIPAddressThresholdService) DeleteNodeIPAddressThreshold(ctx context.Context, req *pb.DeleteNodeIPAddressThresholdRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeIPAddressThresholdDAO.DisableNodeIPAddressThreshold(tx, req.NodeIPAddressThresholdId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindAllEnabledNodeIPAddressThresholds 查找IP的所有阈值
|
||||
func (this *NodeIPAddressThresholdService) FindAllEnabledNodeIPAddressThresholds(ctx context.Context, req *pb.FindAllEnabledNodeIPAddressThresholdsRequest) (*pb.FindAllEnabledNodeIPAddressThresholdsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
thresholds, err := models.SharedNodeIPAddressThresholdDAO.FindAllEnabledThresholdsWithAddrId(tx, req.NodeIPAddressId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbThresholds = []*pb.NodeIPAddressThreshold{}
|
||||
for _, threshold := range thresholds {
|
||||
pbThresholds = append(pbThresholds, &pb.NodeIPAddressThreshold{
|
||||
Id: int64(threshold.Id),
|
||||
ItemsJSON: []byte(threshold.Items),
|
||||
ActionsJSON: []byte(threshold.Actions),
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledNodeIPAddressThresholdsResponse{NodeIPAddressThresholds: pbThresholds}, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledNodeIPAddressThresholds 计算IP阈值的数量
|
||||
func (this *NodeIPAddressThresholdService) CountAllEnabledNodeIPAddressThresholds(ctx context.Context, req *pb.CountAllEnabledNodeIPAddressThresholdsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedNodeIPAddressThresholdDAO.CountAllEnabledThresholdsWithAddrId(tx, req.NodeIPAddressId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// UpdateAllNodeIPAddressThresholds 批量更新阈值
|
||||
func (this *NodeIPAddressThresholdService) UpdateAllNodeIPAddressThresholds(ctx context.Context, req *pb.UpdateAllNodeIPAddressThresholdsRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
var thresholds = []*nodeconfigs.IPAddressThresholdConfig{}
|
||||
err = json.Unmarshal(req.NodeIPAddressThresholdsJSON, &thresholds)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode thresholds failed: " + err.Error())
|
||||
}
|
||||
|
||||
err = models.SharedNodeIPAddressThresholdDAO.DisableAllThresholdsWithAddrId(tx, req.NodeIPAddressId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(thresholds) == 0 {
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
var count = len(thresholds)
|
||||
for index, threshold := range thresholds {
|
||||
var order = count - index
|
||||
if threshold.Id > 0 {
|
||||
err = models.SharedNodeIPAddressThresholdDAO.UpdateThreshold(tx, threshold.Id, threshold.Items, threshold.Actions, order)
|
||||
} else {
|
||||
_, err = models.SharedNodeIPAddressThresholdDAO.CreateThreshold(tx, req.NodeIPAddressId, threshold.Items, threshold.Actions, order)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (this *NodeService) NodeStream(server pb.NodeService_NodeStreamServer) erro
|
||||
}
|
||||
subject := "节点\"" + nodeName + "\"已经恢复在线"
|
||||
msg := "节点\"" + nodeName + "\"已经恢复在线"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, models.MessageTypeNodeActive, models.MessageLevelSuccess, subject, msg, nil)
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, models.MessageTypeNodeActive, models.MessageLevelSuccess, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -46,15 +45,6 @@ func (this *NodeValueService) CreateNodeValue(ctx context.Context, req *pb.Creat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 触发IP阈值
|
||||
// 企业版专有
|
||||
if teaconst.IsPlus {
|
||||
err = models.SharedNodeIPAddressDAO.FireThresholds(tx, role, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 源站相关管理
|
||||
// OriginService 源站相关管理
|
||||
type OriginService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// 创建源站
|
||||
// CreateOrigin 创建源站
|
||||
func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOriginRequest) (*pb.CreateOriginResponse, error) {
|
||||
adminId, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
@@ -58,7 +58,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns)
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.Domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
return &pb.CreateOriginResponse{OriginId: originId}, nil
|
||||
}
|
||||
|
||||
// 修改源站
|
||||
// UpdateOrigin 修改源站
|
||||
func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOriginRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
@@ -112,7 +112,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns)
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.Domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// 查找单个源站信息
|
||||
// FindEnabledOrigin 查找单个源站信息
|
||||
func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEnabledOriginRequest) (*pb.FindEnabledOriginResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
@@ -157,11 +157,12 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
|
||||
PortRange: addr.PortRange,
|
||||
},
|
||||
Description: origin.Description,
|
||||
Domains: origin.DecodeDomains(),
|
||||
}
|
||||
return &pb.FindEnabledOriginResponse{Origin: result}, nil
|
||||
}
|
||||
|
||||
// 查找源站配置
|
||||
// FindEnabledOriginConfig 查找源站配置
|
||||
func (this *OriginService) FindEnabledOriginConfig(ctx context.Context, req *pb.FindEnabledOriginConfigRequest) (*pb.FindEnabledOriginConfigResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,8 +2,10 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
)
|
||||
|
||||
// ServerGroupService 服务分组相关服务
|
||||
@@ -132,3 +134,295 @@ func (this *ServerGroupService) FindEnabledServerGroup(ctx context.Context, req
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindAndInitServerGroupHTTPReverseProxyConfig 查找HTTP反向代理设置
|
||||
func (this *ServerGroupService) FindAndInitServerGroupHTTPReverseProxyConfig(ctx context.Context, req *pb.FindAndInitServerGroupHTTPReverseProxyConfigRequest) (*pb.FindAndInitServerGroupHTTPReverseProxyConfigResponse, error) {
|
||||
// 校验请求
|
||||
adminId, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
reverseProxyRef, err := models.SharedServerGroupDAO.FindHTTPReverseProxyRef(tx, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reverseProxyRef == nil {
|
||||
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, 0, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reverseProxyRef = &serverconfigs.ReverseProxyRef{
|
||||
IsOn: false,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
}
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = models.SharedServerGroupDAO.UpdateHTTPReverseProxy(tx, req.ServerGroupId, refJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
reverseProxyConfig, err := models.SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(reverseProxyConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.FindAndInitServerGroupHTTPReverseProxyConfigResponse{ReverseProxyJSON: configJSON, ReverseProxyRefJSON: refJSON}, nil
|
||||
}
|
||||
|
||||
// FindAndInitServerGroupTCPReverseProxyConfig 查找反向代理设置
|
||||
func (this *ServerGroupService) FindAndInitServerGroupTCPReverseProxyConfig(ctx context.Context, req *pb.FindAndInitServerGroupTCPReverseProxyConfigRequest) (*pb.FindAndInitServerGroupTCPReverseProxyConfigResponse, error) {
|
||||
// 校验请求
|
||||
adminId, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
reverseProxyRef, err := models.SharedServerGroupDAO.FindTCPReverseProxyRef(tx, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reverseProxyRef == nil {
|
||||
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, 0, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reverseProxyRef = &serverconfigs.ReverseProxyRef{
|
||||
IsOn: false,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
}
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = models.SharedServerGroupDAO.UpdateTCPReverseProxy(tx, req.ServerGroupId, refJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
reverseProxyConfig, err := models.SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(reverseProxyConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.FindAndInitServerGroupTCPReverseProxyConfigResponse{ReverseProxyJSON: configJSON, ReverseProxyRefJSON: refJSON}, nil
|
||||
}
|
||||
|
||||
// FindAndInitServerGroupUDPReverseProxyConfig 查找反向代理设置
|
||||
func (this *ServerGroupService) FindAndInitServerGroupUDPReverseProxyConfig(ctx context.Context, req *pb.FindAndInitServerGroupUDPReverseProxyConfigRequest) (*pb.FindAndInitServerGroupUDPReverseProxyConfigResponse, error) {
|
||||
// 校验请求
|
||||
adminId, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
reverseProxyRef, err := models.SharedServerGroupDAO.FindUDPReverseProxyRef(tx, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reverseProxyRef == nil {
|
||||
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, 0, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reverseProxyRef = &serverconfigs.ReverseProxyRef{
|
||||
IsOn: false,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
}
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = models.SharedServerGroupDAO.UpdateUDPReverseProxy(tx, req.ServerGroupId, refJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
reverseProxyConfig, err := models.SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, reverseProxyRef.ReverseProxyId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(reverseProxyConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.FindAndInitServerGroupUDPReverseProxyConfigResponse{ReverseProxyJSON: configJSON, ReverseProxyRefJSON: refJSON}, nil
|
||||
}
|
||||
|
||||
// UpdateServerGroupHTTPReverseProxy 修改服务的反向代理设置
|
||||
func (this *ServerGroupService) UpdateServerGroupHTTPReverseProxy(ctx context.Context, req *pb.UpdateServerGroupHTTPReverseProxyRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 修改配置
|
||||
err = models.SharedServerGroupDAO.UpdateHTTPReverseProxy(tx, req.ServerGroupId, req.ReverseProxyJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerGroupTCPReverseProxy 修改服务的反向代理设置
|
||||
func (this *ServerGroupService) UpdateServerGroupTCPReverseProxy(ctx context.Context, req *pb.UpdateServerGroupTCPReverseProxyRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 修改配置
|
||||
err = models.SharedServerGroupDAO.UpdateTCPReverseProxy(tx, req.ServerGroupId, req.ReverseProxyJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerGroupUDPReverseProxy 修改服务的反向代理设置
|
||||
func (this *ServerGroupService) UpdateServerGroupUDPReverseProxy(ctx context.Context, req *pb.UpdateServerGroupUDPReverseProxyRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 修改配置
|
||||
err = models.SharedServerGroupDAO.UpdateUDPReverseProxy(tx, req.ServerGroupId, req.ReverseProxyJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledServerGroupConfigInfo 取得分组的配置概要信息
|
||||
func (this *ServerGroupService) FindEnabledServerGroupConfigInfo(ctx context.Context, req *pb.FindEnabledServerGroupConfigInfoRequest) (*pb.FindEnabledServerGroupConfigInfoResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
var group *models.ServerGroup
|
||||
if req.ServerGroupId > 0 {
|
||||
group, err = models.SharedServerGroupDAO.FindEnabledServerGroup(tx, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if req.ServerId > 0 {
|
||||
groupIds, err := models.SharedServerDAO.FindServerGroupIds(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(groupIds) > 0 {
|
||||
for _, groupId := range groupIds {
|
||||
group, err = models.SharedServerGroupDAO.FindEnabledServerGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if group == nil {
|
||||
return &pb.FindEnabledServerGroupConfigInfoResponse{
|
||||
HasHTTPReverseProxy: false,
|
||||
HasTCPReverseProxy: false,
|
||||
HasUDPReverseProxy: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var result = &pb.FindEnabledServerGroupConfigInfoResponse{
|
||||
ServerGroupId: int64(group.Id),
|
||||
}
|
||||
|
||||
if len(group.HttpReverseProxy) > 0 {
|
||||
var ref = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(group.HttpReverseProxy), ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.HasHTTPReverseProxy = ref.IsPrior
|
||||
}
|
||||
|
||||
if len(group.TcpReverseProxy) > 0 {
|
||||
var ref = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(group.TcpReverseProxy), ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.HasTCPReverseProxy = ref.IsPrior
|
||||
}
|
||||
|
||||
if len(group.UdpReverseProxy) > 0 {
|
||||
var ref = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(group.UdpReverseProxy), ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.HasUDPReverseProxy = ref.IsPrior
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -221,7 +221,15 @@ func (this *SQLExecutor) checkCluster(db *dbs.DB) error {
|
||||
}
|
||||
|
||||
// 创建默认集群
|
||||
_, err = db.Exec("INSERT INTO edgeNodeClusters (name, useAllAPINodes, state, uniqueId, secret) VALUES (?, ?, ?, ?, ?)", "默认集群", 1, 1, rands.HexString(32), rands.String(32))
|
||||
var uniqueId = rands.HexString(32)
|
||||
var secret = rands.String(32)
|
||||
_, err = db.Exec("INSERT INTO edgeNodeClusters (name, useAllAPINodes, state, uniqueId, secret) VALUES (?, ?, ?, ?, ?)", "默认集群", 1, 1, uniqueId, secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建APIToken
|
||||
_, err = db.Exec("INSERT INTO edgeAPITokens (nodeId, secret, role, state) VALUES (?, ?, 'cluster', 1)", uniqueId, secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ var upgradeFuncs = []*upgradeVersion{
|
||||
{
|
||||
"0.3.0", upgradeV0_3_0,
|
||||
},
|
||||
{
|
||||
"0.3.1", upgradeV0_3_1,
|
||||
},
|
||||
}
|
||||
|
||||
// UpgradeSQLData 升级SQL数据
|
||||
@@ -361,3 +364,32 @@ func upgradeV0_3_0(db *dbs.DB) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// v0.3.1
|
||||
func upgradeV0_3_1(db *dbs.DB) error {
|
||||
// 清空域名统计,已使用分表代替
|
||||
// 因为可能有权限问题,所以我们忽略错误
|
||||
_, _ = db.Exec("TRUNCATE table edgeServerDomainHourlyStats")
|
||||
|
||||
// 升级APIToken
|
||||
ones, _, err := db.FindOnes("SELECT uniqueId,secret FROM edgeNodeClusters")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var uniqueId = one.GetString("uniqueId")
|
||||
var secret = one.GetString("secret")
|
||||
tokenOne, err := db.FindOne("SELECT id FROM edgeAPITokens WHERE nodeId=? LIMIT 1", uniqueId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(tokenOne) == 0 {
|
||||
_, err = db.Exec("INSERT INTO edgeAPITokens (nodeId, secret, role, state) VALUES (?, ?, 'cluster', 1)", uniqueId, secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,3 +20,20 @@ func TestUpgradeSQLData(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
|
||||
func TestUpgradeSQLData_v1_3_1(t *testing.T) {
|
||||
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_new?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = upgradeV0_3_1(db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
@@ -125,7 +126,7 @@ func (this *DNSTaskExecutor) doServer(taskId int64, serverId int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
manager, domainId, domain, clusterDNSName, err := this.findDNSManager(tx, int64(serverDNS.ClusterId))
|
||||
manager, domainId, domain, clusterDNSName, dnsConfig, err := this.findDNSManager(tx, int64(serverDNS.ClusterId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -133,6 +134,10 @@ func (this *DNSTaskExecutor) doServer(taskId int64, serverId int64) error {
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
var ttl int32 = 0
|
||||
if dnsConfig != nil {
|
||||
ttl = dnsConfig.TTL
|
||||
}
|
||||
|
||||
recordName := serverDNS.DnsName
|
||||
recordValue := clusterDNSName + "." + domain + "."
|
||||
@@ -196,6 +201,7 @@ func (this *DNSTaskExecutor) doServer(taskId int64, serverId int64) error {
|
||||
Type: recordType,
|
||||
Value: recordValue,
|
||||
Route: recordRoute,
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -264,7 +270,7 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
}()
|
||||
|
||||
var tx *dbs.Tx
|
||||
manager, domainId, domain, clusterDNSName, err := this.findDNSManager(tx, clusterId)
|
||||
manager, domainId, domain, clusterDNSName, dnsConfig, err := this.findDNSManager(tx, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -273,17 +279,29 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var clusterDomain = clusterDNSName + "." + domain
|
||||
|
||||
var ttl int32 = 0
|
||||
if dnsConfig != nil {
|
||||
ttl = dnsConfig.TTL
|
||||
}
|
||||
|
||||
// 以前的节点记录
|
||||
records, err := manager.GetRecords(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldRecordsMap := map[string]*dnstypes.Record{} // route@value => record
|
||||
var oldRecordsMap = map[string]*dnstypes.Record{} // route@value => record
|
||||
var oldCnameRecordsMap = map[string]*dnstypes.Record{} // cname => record
|
||||
for _, record := range records {
|
||||
if (record.Type == dnstypes.RecordTypeA || record.Type == dnstypes.RecordTypeAAAA) && record.Name == clusterDNSName {
|
||||
key := record.Route + "@" + record.Value
|
||||
oldRecordsMap[key] = record
|
||||
}
|
||||
|
||||
if record.Type == dnstypes.RecordTypeCNAME {
|
||||
oldCnameRecordsMap[record.Name] = record
|
||||
}
|
||||
}
|
||||
|
||||
// 当前的节点记录
|
||||
@@ -311,7 +329,7 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
continue
|
||||
}
|
||||
for _, ipAddress := range ipAddresses {
|
||||
ip := ipAddress.Ip
|
||||
ip := ipAddress.DNSIP()
|
||||
if len(ip) == 0 || ipAddress.CanAccess == 0 || ipAddress.IsUp == 0 || ipAddress.IsOn == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -336,6 +354,7 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
Type: recordType,
|
||||
Value: ip,
|
||||
Route: route,
|
||||
TTL: ttl,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -357,6 +376,80 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 服务域名
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的域名
|
||||
serverDNSNames := []string{}
|
||||
for _, server := range servers {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动设置的CNAME
|
||||
var cnameRecords = []string{}
|
||||
if dnsConfig != nil {
|
||||
cnameRecords = dnsConfig.CNameRecords
|
||||
}
|
||||
for _, cnameRecord := range cnameRecords {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 通知更新域名
|
||||
if isChanged {
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateDomainTask(tx, domainId, dnsmodels.DNSTaskTypeDomainChange)
|
||||
@@ -436,47 +529,53 @@ func (this *DNSTaskExecutor) doDomain(taskId int64, domainId int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *DNSTaskExecutor) findDNSManager(tx *dbs.Tx, clusterId int64) (manager dnsclients.ProviderInterface, domainId int64, domain string, clusterDNSName string, err error) {
|
||||
func (this *DNSTaskExecutor) findDNSManager(tx *dbs.Tx, clusterId int64) (manager dnsclients.ProviderInterface, domainId int64, domain string, clusterDNSName string, dnsConfig *dnsconfigs.ClusterDNSConfig, err error) {
|
||||
clusterDNS, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId, nil)
|
||||
if err != nil {
|
||||
return nil, 0, "", "", err
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
if clusterDNS == nil || len(clusterDNS.DnsName) == 0 || clusterDNS.DnsDomainId <= 0 {
|
||||
return nil, 0, "", "", nil
|
||||
return nil, 0, "", "", nil, nil
|
||||
}
|
||||
|
||||
dnsConfig, err = clusterDNS.DecodeDNSConfig()
|
||||
if err != nil {
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
|
||||
dnsDomain, err := dnsmodels.SharedDNSDomainDAO.FindEnabledDNSDomain(tx, int64(clusterDNS.DnsDomainId), nil)
|
||||
if err != nil {
|
||||
return nil, 0, "", "", err
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
if dnsDomain == nil {
|
||||
return nil, 0, "", "", nil
|
||||
return nil, 0, "", "", nil, nil
|
||||
}
|
||||
providerId := int64(dnsDomain.ProviderId)
|
||||
if providerId <= 0 {
|
||||
return nil, 0, "", "", nil
|
||||
return nil, 0, "", "", nil, nil
|
||||
}
|
||||
|
||||
provider, err := dnsmodels.SharedDNSProviderDAO.FindEnabledDNSProvider(tx, providerId)
|
||||
if err != nil {
|
||||
return nil, 0, "", "", err
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
if provider == nil {
|
||||
return nil, 0, "", "", nil
|
||||
return nil, 0, "", "", nil, nil
|
||||
}
|
||||
|
||||
manager = dnsclients.FindProvider(provider.Type)
|
||||
if manager == nil {
|
||||
remotelogs.Error("DNSTaskExecutor", "unsupported dns provider type '"+provider.Type+"'")
|
||||
return nil, 0, "", "", nil
|
||||
return nil, 0, "", "", nil, nil
|
||||
}
|
||||
params, err := provider.DecodeAPIParams()
|
||||
if err != nil {
|
||||
return nil, 0, "", "", err
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
err = manager.Auth(params)
|
||||
if err != nil {
|
||||
return nil, 0, "", "", err
|
||||
return nil, 0, "", "", nil, err
|
||||
}
|
||||
return manager, int64(dnsDomain.Id), dnsDomain.Name, clusterDNS.DnsName, nil
|
||||
|
||||
return manager, int64(dnsDomain.Id), dnsDomain.Name, clusterDNS.DnsName, dnsConfig, nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
@@ -139,10 +140,10 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
|
||||
// 通知恢复或下线
|
||||
if result.IsOk {
|
||||
message := "健康检查成功,节点\"" + result.Node.Name + "\"已恢复上线"
|
||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeUp, models.MessageLevelSuccess, message, message, nil)
|
||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeUp, models.MessageLevelSuccess, message, message, nil, false)
|
||||
} else {
|
||||
message := "健康检查失败,节点\"" + result.Node.Name + "\"已自动下线"
|
||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeDown, models.MessageLevelError, message, message, nil)
|
||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeDown, models.MessageLevelError, message, message, nil, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,11 +186,11 @@ func (this *HealthCheckExecutor) checkNode(healthCheckConfig *serverconfigs.Heal
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err := net.Dial(network, result.NodeAddr+":"+port)
|
||||
conn, err := net.Dial(network, configutils.QuoteIP(result.NodeAddr)+":"+port)
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
return net.DialTimeout(network, result.NodeAddr+":"+port, timeout)
|
||||
return net.DialTimeout(network, configutils.QuoteIP(result.NodeAddr)+":"+port, timeout)
|
||||
},
|
||||
MaxIdleConns: 1,
|
||||
MaxIdleConnsPerHost: 1,
|
||||
|
||||
@@ -83,7 +83,7 @@ func (this *NodeMonitorTask) monitorCluster(cluster *models.NodeCluster) error {
|
||||
for _, node := range inactiveNodes {
|
||||
subject := "节点\"" + node.Name + "\"已处于离线状态"
|
||||
msg := "节点\"" + node.Name + "\"已处于离线状态"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, clusterId, int64(node.Id), models.MessageTypeNodeInactive, models.LevelError, subject, msg, nil)
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, clusterId, int64(node.Id), models.MessageTypeNodeInactive, models.LevelError, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (this *NSNodeMonitorTask) monitorCluster(cluster *models.NSCluster) error {
|
||||
for _, node := range inactiveNodes {
|
||||
subject := "DNS节点\"" + node.Name + "\"已处于离线状态"
|
||||
msg := "DNS节点\"" + node.Name + "\"已处于离线状态"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(nil, nodeconfigs.NodeRoleDNS, clusterId, int64(node.Id), models.MessageTypeNSNodeInactive, models.LevelError, subject, msg, nil)
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(nil, nodeconfigs.NodeRoleDNS, clusterId, int64(node.Id), models.MessageTypeNSNodeInactive, models.LevelError, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user