Compare commits

...

26 Commits

Author SHA1 Message Date
刘祥超
6b81ffd074 边缘节点版本调整为0.3.1 2021-09-23 20:59:21 +08:00
刘祥超
eff3c77551 分组配置信息中增加分组ID 2021-09-23 14:41:32 +08:00
刘祥超
2089bac52f 可以在分组中设置一些全局配置选项 2021-09-22 19:39:43 +08:00
刘祥超
67760a53ba 域名解析任务可以使用集群ID筛选 2021-09-21 10:56:53 +08:00
刘祥超
d4d7b1fff7 可以设置集群的DNS记录TTL 2021-09-20 20:01:21 +08:00
刘祥超
d121bc86a0 在集群中可以设置自动加入DNS的CNAME记录 2021-09-20 16:37:48 +08:00
刘祥超
7a1bd29f6f 反向代理源站实现使用域名分组 2021-09-20 11:54:45 +08:00
刘祥超
f1af151080 开源版本也显示域名排行 2021-09-19 16:10:34 +08:00
刘祥超
f39d106bef 实现连通性变化发送通知功能 2021-09-18 14:21:56 +08:00
刘祥超
d9c092cd31 修复创建默认集群时没有写入API令牌的Bug 2021-09-16 15:43:07 +08:00
刘祥超
7d1d138e42 优化域名排行查询速度 2021-09-16 09:23:36 +08:00
刘祥超
89bd70819f 增加查找区域监控对象相关结果API 2021-09-15 17:53:34 +08:00
刘祥超
15156b68e3 修复IP地址不能修改在线状态的Bug 2021-09-15 11:45:00 +08:00
刘祥超
92a3b8f375 健康检查只检查启用的IP地址 2021-09-15 10:44:25 +08:00
刘祥超
6a152b7775 调整部分命名 2021-09-14 19:38:44 +08:00
刘祥超
ea915582c1 IP阈值动作增加WebHook 2021-09-14 15:27:48 +08:00
刘祥超
51b938b9c7 IP阈值增加节点分组和集群相关统计项目 2021-09-14 11:36:22 +08:00
刘祥超
c2f559d48e 优化节点设置交互 2021-09-13 16:47:40 +08:00
刘祥超
a96c1434b6 健康检查支持IPv6地址的节点 2021-09-13 13:46:20 +08:00
刘祥超
d135442a52 IP地址支持手动上线和从备用IP中恢复 2021-09-13 13:45:58 +08:00
刘祥超
0b8501a724 实现节点自动切换到备用IP 2021-09-13 10:51:05 +08:00
刘祥超
7fcc2b7dba 实现基础的IP地址阈值 2021-09-12 20:21:42 +08:00
刘祥超
1ea7fe0213 实现基本的监控终端管理 2021-09-08 19:34:31 +08:00
刘祥超
838d33648f 通过DNS方式申请ACME证书时支持二级域名 2021-09-08 18:23:37 +08:00
刘祥超
6cf4a8ea3e 对域名统计进行分表处理 2021-09-08 17:32:08 +08:00
刘祥超
15c40d6c96 版本号修改0.3.1 2021-09-08 17:31:18 +08:00
78 changed files with 2685 additions and 384 deletions

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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"
)

View File

@@ -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).

View File

@@ -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).

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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 {

View File

@@ -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).

View File

@@ -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")
}

View File

@@ -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)
}

View File

@@ -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))
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 ""
}

View 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()
}

View File

@@ -0,0 +1,6 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View 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{}
}

View 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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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).

View File

@@ -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) {

View File

@@ -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{} // 状态
}

View File

@@ -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
}

View File

@@ -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()
}

View 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()
}

View File

@@ -0,0 +1,6 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View 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{}
}

View File

@@ -0,0 +1 @@
package models

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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{} // 连续上线次数

View File

@@ -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
}

View File

@@ -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{}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -15,4 +15,5 @@ type Record struct {
Type RecordType `json:"type"`
Value string `json:"value"`
Route string `json:"route"`
TTL int32 `json:"ttl"`
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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),
})
}
// 节点排行

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -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,
})

View 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()
}

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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
}