1.4.5.2
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// ReportNodeGroupService 监控节点分组
|
||||
type ReportNodeGroupService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CreateReportNodeGroup 创建分组
|
||||
func (this *ReportNodeGroupService) CreateReportNodeGroup(ctx context.Context, req *pb.CreateReportNodeGroupRequest) (*pb.CreateReportNodeGroupResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
groupId, err := models.SharedReportNodeGroupDAO.CreateGroup(tx, req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CreateReportNodeGroupResponse{ReportNodeGroupId: groupId}, nil
|
||||
}
|
||||
|
||||
// UpdateReportNodeGroup 修改分组
|
||||
func (this *ReportNodeGroupService) UpdateReportNodeGroup(ctx context.Context, req *pb.UpdateReportNodeGroupRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedReportNodeGroupDAO.UpdateGroup(tx, req.ReportNodeGroupId, req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteReportNodeGroup 删除分组
|
||||
func (this *ReportNodeGroupService) DeleteReportNodeGroup(ctx context.Context, req *pb.DeleteReportNodeGroupRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedReportNodeGroupDAO.DisableReportNodeGroup(tx, req.ReportNodeGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindAllEnabledReportNodeGroups 查找所有分组
|
||||
func (this *ReportNodeGroupService) FindAllEnabledReportNodeGroups(ctx context.Context, req *pb.FindAllEnabledReportNodeGroupsRequest) (*pb.FindAllEnabledReportNodeGroupsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
groups, err := models.SharedReportNodeGroupDAO.FindAllEnabledGroups(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbGroups = []*pb.ReportNodeGroup{}
|
||||
for _, group := range groups {
|
||||
pbGroups = append(pbGroups, &pb.ReportNodeGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledReportNodeGroupsResponse{ReportNodeGroups: pbGroups}, nil
|
||||
}
|
||||
|
||||
// FindEnabledReportNodeGroup 查找单个分组
|
||||
func (this *ReportNodeGroupService) FindEnabledReportNodeGroup(ctx context.Context, req *pb.FindEnabledReportNodeGroupRequest) (*pb.FindEnabledReportNodeGroupResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
group, err := models.SharedReportNodeGroupDAO.FindEnabledReportNodeGroup(tx, req.ReportNodeGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
return &pb.FindEnabledReportNodeGroupResponse{ReportNodeGroup: nil}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledReportNodeGroupResponse{
|
||||
ReportNodeGroup: &pb.ReportNodeGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledReportNodeGroups 计算所有分组数量
|
||||
func (this *ReportNodeGroupService) CountAllEnabledReportNodeGroups(ctx context.Context, req *pb.CountAllEnabledReportNodeGroupsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedReportNodeGroupDAO.CountAllEnabledGroups(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
// +build plus
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"google.golang.org/grpc/peer"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ReportNodeService 监控终端服务
|
||||
type ReportNodeService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CreateReportNode 添加终端
|
||||
func (this *ReportNodeService) CreateReportNode(ctx context.Context, req *pb.CreateReportNodeRequest) (*pb.CreateReportNodeResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
reporterId, err := models.SharedReportNodeDAO.CreateReportNode(tx, req.Name, req.Location, req.Isp, req.AllowIPs, req.ReportNodeGroupIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateReportNodeResponse{ReportNodeId: reporterId}, nil
|
||||
}
|
||||
|
||||
// DeleteReportNode 删除终端
|
||||
func (this *ReportNodeService) DeleteReportNode(ctx context.Context, req *pb.DeleteReportNodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedReportNodeDAO.DisableReportNode(tx, req.ReportNodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateReportNode 修改终端
|
||||
func (this *ReportNodeService) UpdateReportNode(ctx context.Context, req *pb.UpdateReportNodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedReportNodeDAO.UpdateReportNode(tx, req.ReportNodeId, req.Name, req.Location, req.Isp, req.AllowIPs, req.ReportNodeGroupIds, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountAllEnabledReportNodes 计算终端数量
|
||||
func (this *ReportNodeService) CountAllEnabledReportNodes(ctx context.Context, req *pb.CountAllEnabledReportNodesRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedReportNodeDAO.CountAllEnabledReportNodes(tx, req.ReportNodeGroupId, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledReportNodes 列出单页终端
|
||||
func (this *ReportNodeService) ListEnabledReportNodes(ctx context.Context, req *pb.ListEnabledReportNodesRequest) (*pb.ListEnabledReportNodesResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
ones, err := models.SharedReportNodeDAO.ListEnabledReportNodes(tx, req.ReportNodeGroupId, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbNodes = []*pb.ReportNode{}
|
||||
for _, one := range ones {
|
||||
var pbGroups = []*pb.ReportNodeGroup{}
|
||||
var groupIds = one.DecodeGroupIds()
|
||||
for _, groupId := range groupIds {
|
||||
group, err := models.SharedReportNodeGroupDAO.FindEnabledReportNodeGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
pbGroups = append(pbGroups, &pb.ReportNodeGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
|
||||
pbNodes = append(pbNodes, &pb.ReportNode{
|
||||
Id: int64(one.Id),
|
||||
UniqueId: one.UniqueId,
|
||||
Secret: one.Secret,
|
||||
IsOn: one.IsOn,
|
||||
Name: one.Name,
|
||||
Location: one.Location,
|
||||
Isp: one.Isp,
|
||||
IsActive: one.IsActive,
|
||||
StatusJSON: one.Status,
|
||||
AllowIPs: one.DecodeAllowIPs(),
|
||||
ReportNodeGroups: pbGroups,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListEnabledReportNodesResponse{
|
||||
ReportNodes: pbNodes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledReportNode 查找单个终端
|
||||
func (this *ReportNodeService) FindEnabledReportNode(ctx context.Context, req *pb.FindEnabledReportNodeRequest) (*pb.FindEnabledReportNodeResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
node, err := models.SharedReportNodeDAO.FindEnabledReportNode(tx, req.ReportNodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if node == nil {
|
||||
return &pb.FindEnabledReportNodeResponse{ReportNode: nil}, nil
|
||||
}
|
||||
|
||||
var pbGroups = []*pb.ReportNodeGroup{}
|
||||
var groupIds = node.DecodeGroupIds()
|
||||
for _, groupId := range groupIds {
|
||||
group, err := models.SharedReportNodeGroupDAO.FindEnabledReportNodeGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
pbGroups = append(pbGroups, &pb.ReportNodeGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindEnabledReportNodeResponse{ReportNode: &pb.ReportNode{
|
||||
Id: int64(node.Id),
|
||||
UniqueId: node.UniqueId,
|
||||
Secret: node.Secret,
|
||||
IsOn: node.IsOn,
|
||||
Name: node.Name,
|
||||
Location: node.Location,
|
||||
Isp: node.Isp,
|
||||
IsActive: node.IsActive,
|
||||
StatusJSON: node.Status,
|
||||
AllowIPs: node.DecodeAllowIPs(),
|
||||
ReportNodeGroups: pbGroups,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// UpdateReportNodeStatus 更新节点状态
|
||||
func (this *ReportNodeService) UpdateReportNodeStatus(ctx context.Context, req *pb.UpdateReportNodeStatusRequest) (*pb.RPCSuccess, error) {
|
||||
_, nodeId, err := this.ValidateNodeId(ctx, rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = validateClient(tx, nodeId, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var status = &reporterconfigs.Status{}
|
||||
err = json.Unmarshal(req.StatusJSON, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status.UpdatedAt = time.Now().Unix()
|
||||
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if ok {
|
||||
host, _, _ := net.SplitHostPort(p.Addr.String())
|
||||
if len(host) > 0 {
|
||||
status.IP = host
|
||||
|
||||
var result = iplibrary.LookupIP(host)
|
||||
if result != nil && result.IsOk() {
|
||||
status.Location = result.Summary()
|
||||
status.ISP = result.ProviderName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedReportNodeDAO.UpdateNodeStatus(tx, nodeId, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindCurrentReportNodeConfig 获取当前节点信息
|
||||
func (this *ReportNodeService) FindCurrentReportNodeConfig(ctx context.Context, req *pb.FindCurrentReportNodeConfigRequest) (*pb.FindCurrentReportNodeConfigResponse, error) {
|
||||
_, nodeId, err := this.ValidateNodeId(ctx, rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = validateClient(tx, nodeId, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config, err := models.SharedReportNodeDAO.ComposeConfig(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindCurrentReportNodeConfigResponse{ReportNodeJSON: configJSON}, nil
|
||||
}
|
||||
|
||||
// FindReportNodeTasks 读取任务
|
||||
func (this *ReportNodeService) FindReportNodeTasks(ctx context.Context, req *pb.FindReportNodeTasksRequest) (*pb.FindReportNodeTasksResponse, error) {
|
||||
_, nodeId, err := this.ValidateNodeId(ctx, rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = validateClient(tx, nodeId, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result = &pb.FindReportNodeTasksResponse{}
|
||||
|
||||
var ipTasks = []*reporterconfigs.IPTask{}
|
||||
|
||||
// 所有的集群
|
||||
// TODO 将来支持NS节点
|
||||
clusters, err := models.SharedNodeClusterDAO.FindAllEnableClusters(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, cluster := range clusters {
|
||||
if !cluster.IsOn {
|
||||
continue
|
||||
}
|
||||
var clusterId = int64(cluster.Id)
|
||||
|
||||
port, err := models.SharedServerDAO.FindFirstHTTPOrHTTPSPortWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if port <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 读取所有IP地址
|
||||
addrList, err := models.SharedNodeIPAddressDAO.FindAllAccessibleIPAddressesWithClusterId(tx, nodeconfigs.NodeRoleNode, clusterId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range addrList {
|
||||
if !addr.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
var addrIP = addr.Ip
|
||||
var backupIP = addr.DecodeBackupIP()
|
||||
if len(backupIP) > 0 {
|
||||
addrIP = backupIP
|
||||
}
|
||||
|
||||
ipTasks = append(ipTasks, &reporterconfigs.IPTask{
|
||||
AddrId: int64(addr.Id),
|
||||
IP: addrIP,
|
||||
Port: port,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ipTasksJSON, err := json.Marshal(ipTasks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.IpAddrTasksJSON = ipTasksJSON
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindLatestReportNodeVersion 取得最新的版本号
|
||||
func (this *ReportNodeService) FindLatestReportNodeVersion(ctx context.Context, req *pb.FindLatestReportNodeVersionRequest) (*pb.FindLatestReportNodeVersionResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.FindLatestReportNodeVersionResponse{
|
||||
Version: teaconst.ReportNodeVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountAllReportNodeTasks 计算任务数量
|
||||
func (this *ReportNodeService) CountAllReportNodeTasks(ctx context.Context, req *pb.CountAllReportNodeTasksRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var count int64
|
||||
var tx *dbs.Tx
|
||||
|
||||
switch req.Type {
|
||||
case reporterconfigs.TaskTypeIPAddr:
|
||||
count, err = models.SharedNodeIPAddressDAO.CountAllAccessibleIPAddressesWithClusterId(tx, req.Role, req.NodeClusterId)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListReportNodeTasks 列出单页任务
|
||||
func (this *ReportNodeService) ListReportNodeTasks(ctx context.Context, req *pb.ListReportNodeTasksRequest) (*pb.ListReportNodeTasksResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
switch req.Type {
|
||||
case reporterconfigs.TaskTypeIPAddr:
|
||||
port, err := models.SharedServerDAO.FindFirstHTTPOrHTTPSPortWithClusterId(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addrs, err := models.SharedNodeIPAddressDAO.ListAccessibleIPAddressesWithClusterId(tx, req.Role, req.NodeClusterId, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbTasks = []*pb.IPAddrReportTask{}
|
||||
for _, addr := range addrs {
|
||||
var addrIP = addr.Ip
|
||||
var backupIP = addr.DecodeBackupIP()
|
||||
if len(backupIP) > 0 {
|
||||
addrIP = backupIP
|
||||
}
|
||||
|
||||
// 地址
|
||||
var pbAddr = &pb.NodeIPAddress{
|
||||
Id: int64(addr.Id),
|
||||
NodeId: int64(addr.NodeId),
|
||||
Name: addr.Name,
|
||||
Ip: addrIP,
|
||||
Description: addr.Description,
|
||||
CanAccess: addr.CanAccess,
|
||||
IsOn: addr.IsOn,
|
||||
IsUp: addr.IsUp,
|
||||
Role: addr.Role,
|
||||
}
|
||||
var connectivity = addr.DecodeConnectivity()
|
||||
|
||||
pbTasks = append(pbTasks, &pb.IPAddrReportTask{
|
||||
Ip: addr.Ip,
|
||||
Port: types.Int32(port),
|
||||
NodeIPAddress: pbAddr,
|
||||
CostMs: float32(connectivity.CostMs),
|
||||
Level: connectivity.Level,
|
||||
Connectivity: float32(connectivity.Percent),
|
||||
})
|
||||
}
|
||||
return &pb.ListReportNodeTasksResponse{
|
||||
IpAddrReportTasks: pbTasks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.ListReportNodeTasksResponse{}, nil
|
||||
}
|
||||
|
||||
// UpdateReportNodeGlobalSetting 修改全局设置
|
||||
func (this *ReportNodeService) UpdateReportNodeGlobalSetting(ctx context.Context, req *pb.UpdateReportNodeGlobalSetting) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedSysSettingDAO.UpdateSetting(tx, systemconfigs.SettingCodeReportNodeGlobalSetting, req.SettingJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// ReadReportNodeGlobalSetting 读取全局设置
|
||||
func (this *ReportNodeService) ReadReportNodeGlobalSetting(ctx context.Context, req *pb.ReadReportNodeGlobalSettingRequest) (*pb.ReadReportNodeGlobalSettingResponse, error) {
|
||||
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
valueJSON, err := models.SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeReportNodeGlobalSetting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var setting = reporterconfigs.DefaultGlobalSetting()
|
||||
if len(valueJSON) > 0 {
|
||||
err = json.Unmarshal(valueJSON, setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 重新编码
|
||||
valueJSON, err = json.Marshal(setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ReadReportNodeGlobalSettingResponse{
|
||||
SettingJSON: valueJSON,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
//go:build plus
|
||||
// +build plus
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CommandRequest 命令请求相关
|
||||
type CommandRequest struct {
|
||||
Id int64
|
||||
Code string
|
||||
CommandJSON []byte
|
||||
}
|
||||
|
||||
type CommandRequestWaiting struct {
|
||||
Timestamp int64
|
||||
Chan chan *pb.ReportNodeStreamMessage
|
||||
}
|
||||
|
||||
func (this *CommandRequestWaiting) Close() {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
close(this.Chan)
|
||||
}
|
||||
|
||||
var responseChanMap = map[int64]*CommandRequestWaiting{} // request id => response
|
||||
var commandRequestId = int64(0)
|
||||
|
||||
var nodeLocker = &sync.Mutex{}
|
||||
var requestChanMap = map[int64]chan *CommandRequest{} // node id => chan
|
||||
|
||||
func NextCommandRequestId() int64 {
|
||||
return atomic.AddInt64(&commandRequestId, 1)
|
||||
}
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理WaitingChannelMap
|
||||
goman.New(func() {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
for range ticker.C {
|
||||
nodeLocker.Lock()
|
||||
for requestId, request := range responseChanMap {
|
||||
if time.Now().Unix()-request.Timestamp > 3600 {
|
||||
responseChanMap[requestId].Close()
|
||||
delete(responseChanMap, requestId)
|
||||
}
|
||||
}
|
||||
nodeLocker.Unlock()
|
||||
}
|
||||
})
|
||||
|
||||
// 自动同步连接到本API节点的Report节点任务
|
||||
goman.New(func() {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
// TODO 未来支持同步边缘节点
|
||||
var ticker = time.NewTicker(3 * time.Second)
|
||||
for range ticker.C {
|
||||
nodeIds, err := models.SharedNodeTaskDAO.FindAllDoingNodeIds(nil, nodeconfigs.NodeRoleReport)
|
||||
if err != nil {
|
||||
remotelogs.Error("ReportNodeService_SYNC", err.Error())
|
||||
continue
|
||||
}
|
||||
nodeLocker.Lock()
|
||||
for _, nodeId := range nodeIds {
|
||||
c, ok := requestChanMap[nodeId]
|
||||
if ok {
|
||||
select {
|
||||
case c <- &CommandRequest{
|
||||
Id: NextCommandRequestId(),
|
||||
Code: reporterconfigs.MessageCodeNewNodeTask,
|
||||
CommandJSON: nil,
|
||||
}:
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeLocker.Unlock()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ReportNodeStream 节点stream
|
||||
func (this *ReportNodeService) ReportNodeStream(server pb.ReportNodeService_ReportNodeStreamServer) error {
|
||||
// TODO 使用此stream快速通知Reporter节点更新
|
||||
// 校验节点
|
||||
_, nodeId, err := this.ValidateNodeId(server.Context(), rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = validateClient(tx, nodeId, server.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 返回连接成功
|
||||
{
|
||||
apiConfig, err := configs.SharedAPIConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
connectedMessage := &reporterconfigs.ConnectedAPINodeMessage{APINodeId: apiConfig.NumberId()}
|
||||
connectedMessageJSON, err := json.Marshal(connectedMessage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
err = server.Send(&pb.ReportNodeStreamMessage{
|
||||
Code: reporterconfigs.MessageCodeConnectedAPINode,
|
||||
DataJSON: connectedMessageJSON,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//logs.Println("[RPC]accepted ns node '" + types.String(nodeId) + "' connection")
|
||||
|
||||
// 标记为活跃状态
|
||||
oldIsActive, err := models.SharedReportNodeDAO.FindNodeActive(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !oldIsActive {
|
||||
err = models.SharedReportNodeDAO.UpdateNodeActive(tx, nodeId, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送恢复消息
|
||||
nodeName, err := models.SharedReportNodeDAO.FindReportNodeName(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subject := "区域监控节点\"" + nodeName + "\"已经恢复在线"
|
||||
msg := "区域监控节点\"" + nodeName + "\"已经恢复在线"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, nodeconfigs.NodeRoleReport, 0, nodeId, models.MessageTypeReportNodeActive, models.MessageLevelSuccess, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nodeLocker.Lock()
|
||||
requestChan, ok := requestChanMap[nodeId]
|
||||
if !ok {
|
||||
requestChan = make(chan *CommandRequest, 1024)
|
||||
requestChanMap[nodeId] = requestChan
|
||||
}
|
||||
nodeLocker.Unlock()
|
||||
|
||||
defer func() {
|
||||
nodeLocker.Lock()
|
||||
delete(requestChanMap, nodeId)
|
||||
nodeLocker.Unlock()
|
||||
}()
|
||||
|
||||
// 发送请求
|
||||
goman.New(func() {
|
||||
for {
|
||||
select {
|
||||
case <-server.Context().Done():
|
||||
return
|
||||
case commandRequest := <-requestChan:
|
||||
// logs.Println("[RPC]sending command '" + commandRequest.Code + "' to node '" + strconv.FormatInt(nodeId, 10) + "'")
|
||||
retries := 3 // 错误重试次数
|
||||
for i := 0; i < retries; i++ {
|
||||
err := server.Send(&pb.ReportNodeStreamMessage{
|
||||
RequestId: commandRequest.Id,
|
||||
Code: commandRequest.Code,
|
||||
DataJSON: commandRequest.CommandJSON,
|
||||
})
|
||||
if err != nil {
|
||||
if i == retries-1 {
|
||||
logs.Println("[RPC]send command '" + commandRequest.Code + "' failed: " + err.Error())
|
||||
} else {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 接受请求
|
||||
for {
|
||||
req, err := server.Recv()
|
||||
if err != nil {
|
||||
// 修改节点状态
|
||||
err1 := models.SharedReportNodeDAO.UpdateNodeActive(tx, nodeId, false)
|
||||
if err1 != nil {
|
||||
logs.Println(err1.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func(req *pb.ReportNodeStreamMessage) {
|
||||
// 因为 responseChan.Chan 有被关闭的风险,所以我们使用recover防止panic
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
nodeLocker.Lock()
|
||||
responseChan, ok := responseChanMap[req.RequestId]
|
||||
if ok {
|
||||
select {
|
||||
case responseChan.Chan <- req:
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
nodeLocker.Unlock()
|
||||
}(req)
|
||||
}
|
||||
}
|
||||
|
||||
// SendCommandToReportNode 向节点发送命令
|
||||
func (this *ReportNodeService) SendCommandToReportNode(ctx context.Context, req *pb.ReportNodeStreamMessage) (*pb.ReportNodeStreamMessage, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeId := req.ReportNodeId
|
||||
if nodeId <= 0 {
|
||||
return nil, errors.New("node id should not be less than 0")
|
||||
}
|
||||
|
||||
nodeLocker.Lock()
|
||||
requestChan, ok := requestChanMap[nodeId]
|
||||
nodeLocker.Unlock()
|
||||
|
||||
if !ok {
|
||||
return &pb.ReportNodeStreamMessage{
|
||||
RequestId: req.RequestId,
|
||||
IsOk: false,
|
||||
Message: "node '" + strconv.FormatInt(nodeId, 10) + "' not connected yet",
|
||||
}, nil
|
||||
}
|
||||
|
||||
req.RequestId = NextCommandRequestId()
|
||||
|
||||
select {
|
||||
case requestChan <- &CommandRequest{
|
||||
Id: req.RequestId,
|
||||
Code: req.Code,
|
||||
CommandJSON: req.DataJSON,
|
||||
}:
|
||||
// 加入到等待队列中
|
||||
respChan := make(chan *pb.ReportNodeStreamMessage, 1)
|
||||
waiting := &CommandRequestWaiting{
|
||||
Timestamp: time.Now().Unix(),
|
||||
Chan: respChan,
|
||||
}
|
||||
|
||||
nodeLocker.Lock()
|
||||
responseChanMap[req.RequestId] = waiting
|
||||
nodeLocker.Unlock()
|
||||
|
||||
// 等待响应
|
||||
timeoutSeconds := req.TimeoutSeconds
|
||||
if timeoutSeconds <= 0 {
|
||||
timeoutSeconds = 10
|
||||
}
|
||||
timeout := time.NewTimer(time.Duration(timeoutSeconds) * time.Second)
|
||||
select {
|
||||
case resp := <-respChan:
|
||||
// 从队列中删除
|
||||
nodeLocker.Lock()
|
||||
delete(responseChanMap, req.RequestId)
|
||||
waiting.Close()
|
||||
nodeLocker.Unlock()
|
||||
|
||||
if resp == nil {
|
||||
return &pb.ReportNodeStreamMessage{
|
||||
RequestId: req.RequestId,
|
||||
Code: req.Code,
|
||||
Message: "response timeout",
|
||||
IsOk: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
case <-timeout.C:
|
||||
// 从队列中删除
|
||||
nodeLocker.Lock()
|
||||
delete(responseChanMap, req.RequestId)
|
||||
waiting.Close()
|
||||
nodeLocker.Unlock()
|
||||
|
||||
return &pb.ReportNodeStreamMessage{
|
||||
RequestId: req.RequestId,
|
||||
Code: req.Code,
|
||||
Message: "response timeout over " + fmt.Sprintf("%d", timeoutSeconds) + " seconds",
|
||||
IsOk: false,
|
||||
}, nil
|
||||
}
|
||||
default:
|
||||
return &pb.ReportNodeStreamMessage{
|
||||
RequestId: req.RequestId,
|
||||
Code: req.Code,
|
||||
Message: "command queue is full over " + strconv.Itoa(len(requestChan)),
|
||||
IsOk: false,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ReportResultService 区域监控报告结果
|
||||
type ReportResultService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CountAllReportResults 计算监控结果数量
|
||||
func (this *ReportResultService) CountAllReportResults(ctx context.Context, req *pb.CountAllReportResultsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedReportResultDAO.CountAllResults(tx, req.ReportNodeId, req.Level, types.Int8(req.OkState))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListReportResults 列出单页监控结果
|
||||
func (this *ReportResultService) ListReportResults(ctx context.Context, req *pb.ListReportResultsRequest) (*pb.ListReportResultsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
results, err := models.SharedReportResultDAO.ListResults(tx, req.ReportNodeId, types.Int8(req.OkState), req.Level, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbResults = []*pb.ReportResult{}
|
||||
for _, result := range results {
|
||||
pbResults = append(pbResults, &pb.ReportResult{
|
||||
Id: int64(result.Id),
|
||||
Type: result.Type,
|
||||
TargetId: int64(result.TargetId),
|
||||
TargetDesc: result.TargetDesc,
|
||||
ReportNodeId: int64(result.ReportNodeId),
|
||||
IsOk: result.IsOk,
|
||||
CostMs: float32(result.CostMs),
|
||||
Error: result.Error,
|
||||
UpdatedAt: int64(result.UpdatedAt),
|
||||
Level: result.Level,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListReportResultsResponse{
|
||||
ReportResults: pbResults,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateReportResults 上传报告结果
|
||||
func (this *ReportResultService) UpdateReportResults(ctx context.Context, req *pb.UpdateReportResultsRequest) (*pb.RPCSuccess, error) {
|
||||
_, nodeId, err := this.ValidateNodeId(ctx, rpcutils.UserTypeReport)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !teaconst.IsPlus {
|
||||
return nil, errors.New("the commercial version is expired.")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = validateClient(tx, nodeId, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置
|
||||
var setting = reporterconfigs.DefaultGlobalSetting()
|
||||
settingJSON, err := models.SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeReportNodeGlobalSetting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(settingJSON) > 0 {
|
||||
err = json.Unmarshal(settingJSON, setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, result := range req.ReportResults {
|
||||
// 更新数据
|
||||
err := models.SharedReportResultDAO.UpdateResult(tx, result.Type, result.TargetId, result.TargetDesc, nodeId, result.Level, result.IsOk, float64(result.CostMs), result.Error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 更新对象状态
|
||||
costMs, err := models.SharedReportResultDAO.FindAvgCostMsWithTarget(tx, result.Type, result.TargetId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
level, err := models.SharedReportResultDAO.FindAvgLevelWithTarget(tx, result.Type, result.TargetId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
percent, err := models.SharedReportResultDAO.FindConnectivityWithTargetPercent(tx, result.Type, result.TargetId, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 是否应该通知
|
||||
if setting != nil && percent < setting.MinNotifyConnectivity {
|
||||
switch result.Type {
|
||||
case reporterconfigs.TaskTypeIPAddr:
|
||||
addr, err := models.SharedNodeIPAddressDAO.FindEnabledAddress(tx, result.TargetId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addr != nil {
|
||||
var nodeId = int64(addr.NodeId)
|
||||
clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var messageSubject = "IP地址:" + addr.Ip + "连通性低于" + types.String(setting.MinNotifyConnectivity) + "%"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(tx, addr.Role, clusterId, nodeId, models.MessageTypeConnectivity, models.LevelError, messageSubject, messageSubject, maps.Map{"addrId": addr.Id}.AsJSON(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedMessageTaskDAO.CreateMessageTasks(tx, addr.Role, clusterId, nodeId, 0, models.MessageTypeConnectivity, messageSubject, messageSubject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 发送外部通知
|
||||
if len(setting.NotifyWebHookURL) > 0 {
|
||||
var client = utils.SharedHttpClient(10 * time.Second)
|
||||
var url = setting.NotifyWebHookURL
|
||||
var args = "role=" + addr.Role + "&clusterId=" + types.String(clusterId) + "&nodeId=" + types.String(nodeId) + "&addressId=" + types.String(addr.Id) + "&ip=" + addr.Ip
|
||||
var hasQuestionMark = strings.Contains(url, "?")
|
||||
if hasQuestionMark {
|
||||
url += "&" + args
|
||||
} else {
|
||||
url += "?" + args
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
// 不阻断执行
|
||||
remotelogs.Error("ReportResultService.UpdateReportResults", "notify url '"+url+"' failed: "+err.Error())
|
||||
} else {
|
||||
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
// 不阻断执行
|
||||
remotelogs.Error("ReportResultService.UpdateReportResults", "notify url '"+url+"' failed: "+err.Error())
|
||||
} else {
|
||||
_ = resp.Body.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存
|
||||
switch result.Type {
|
||||
case reporterconfigs.TaskTypeIPAddr:
|
||||
err = models.SharedNodeIPAddressDAO.UpdateAddressConnectivity(tx, result.TargetId, &nodeconfigs.Connectivity{
|
||||
CostMs: costMs,
|
||||
Level: level,
|
||||
Percent: percent * 100,
|
||||
UpdatedAt: time.Now().Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindAllReportResults 查询某个对象的监控结果
|
||||
func (this *ReportResultService) FindAllReportResults(ctx context.Context, req *pb.FindAllReportResultsRequest) (*pb.FindAllReportResultsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
results, err := models.SharedReportResultDAO.FindAllResults(tx, req.Type, req.TargetId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbResults = []*pb.ReportResult{}
|
||||
for _, result := range results {
|
||||
pbResults = append(pbResults, &pb.ReportResult{
|
||||
Id: int64(result.Id),
|
||||
Type: result.Type,
|
||||
TargetId: int64(result.TargetId),
|
||||
TargetDesc: result.TargetDesc,
|
||||
ReportNodeId: int64(result.ReportNodeId),
|
||||
IsOk: result.IsOk,
|
||||
CostMs: float32(result.CostMs),
|
||||
Error: result.Error,
|
||||
UpdatedAt: int64(result.UpdatedAt),
|
||||
Level: result.Level,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllReportResultsResponse{
|
||||
ReportResults: pbResults,
|
||||
}, nil
|
||||
}
|
||||
40
EdgeAPI/internal/rpc/services/reporters/utils.go
Normal file
40
EdgeAPI/internal/rpc/services/reporters/utils.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package reporters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"google.golang.org/grpc/peer"
|
||||
"net"
|
||||
)
|
||||
|
||||
// 校验客户端IP
|
||||
func validateClient(tx *dbs.Tx, nodeId int64, ctx context.Context) error {
|
||||
allowIPs, err := models.SharedReportNodeDAO.FindNodeAllowIPs(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(allowIPs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if ok {
|
||||
host, _, _ := net.SplitHostPort(p.Addr.String())
|
||||
if len(host) > 0 {
|
||||
for _, ip := range allowIPs {
|
||||
r, err := shared.ParseIPRange(ip)
|
||||
if err == nil && r != nil {
|
||||
if r.Contains(host) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.New("client was not allowed")
|
||||
}
|
||||
Reference in New Issue
Block a user