商业版支持L2节点

This commit is contained in:
刘祥超
2022-04-04 12:08:08 +08:00
parent d884777a55
commit cd7e01c2f0
10 changed files with 305 additions and 28 deletions

View File

@@ -1,7 +1,9 @@
package models
import (
"crypto/sha256"
"encoding/json"
"fmt"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
@@ -191,7 +193,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, isOn bool) error {
func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId int64, secondaryClusterIds []int64, groupId int64, regionId int64, isOn bool, level int) error {
if nodeId <= 0 {
return errors.New("invalid nodeId")
}
@@ -202,7 +204,16 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
return err
}
op := NewNodeOperator()
// 老的级别
oldLevel, err := this.Query(tx).
Pk(nodeId).
Result("level").
FindIntCol(0)
if err != nil {
return err
}
var op = NewNodeOperator()
op.Id = nodeId
op.Name = name
op.ClusterId = clusterId
@@ -228,6 +239,11 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
op.RegionId = regionId
op.LatestVersion = dbs.SQL("latestVersion+1")
op.IsOn = isOn
if teaconst.IsPlus {
op.Level = level
}
err = this.Save(tx, op)
if err != nil {
return err
@@ -238,7 +254,7 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
return err
}
// 通知老的集群更新
// 通知老的集群DNS更新
for _, oldClusterId := range oldClusterIds {
if oldClusterId != clusterId && !lists.ContainsInt64(secondaryClusterIds, oldClusterId) {
err = dns.SharedDNSTaskDAO.CreateClusterTask(tx, oldClusterId, dns.DNSTaskTypeClusterChange)
@@ -248,6 +264,14 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
}
}
// 通知子级级别变更
if oldLevel > 1 || level > 1 {
err = this.NotifyLevelUpdate(tx, nodeId)
if err != nil {
return err
}
}
return this.NotifyDNSUpdate(tx, nodeId)
}
@@ -278,6 +302,7 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
keyword string,
groupId int64,
regionId int64,
level int32,
includeSecondaryNodes bool,
order string,
offset int64,
@@ -337,6 +362,11 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
query.Attr("regionId", regionId)
}
// 级别
if level > 0 {
query.Attr("level", level)
}
// 排序
switch order {
case "cpuAsc":
@@ -355,6 +385,8 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
query.Asc("IF(JSON_EXTRACT(status, '$.updatedAt')>UNIX_TIMESTAMP()-120, IFNULL(JSON_EXTRACT(status, '$.trafficOutBytes'), 0), 0)")
case "trafficOutDesc":
query.Desc("IF(JSON_EXTRACT(status, '$.updatedAt')>UNIX_TIMESTAMP()-120, IFNULL(JSON_EXTRACT(status, '$.trafficOutBytes'), 0), 0)")
default:
query.Desc("level")
}
query.DescPk()
@@ -400,6 +432,37 @@ func (this *NodeDAO) FindNodeClusterId(tx *dbs.Tx, nodeId int64) (int64, error)
return types.Int64(col), err
}
// FindNodeLevel 获取节点级别
func (this *NodeDAO) FindNodeLevel(tx *dbs.Tx, nodeId int64) (int, error) {
level, err := this.Query(tx).
Pk(nodeId).
Result("level").
FindIntCol(0)
if err != nil {
return 0, err
}
if level < 1 {
level = 1
}
return level, nil
}
// FindNodeLevelInfo 获取节点级别相关信息
func (this *NodeDAO) FindNodeLevelInfo(tx *dbs.Tx, nodeId int64) (*Node, error) {
one, err := this.Query(tx).
Pk(nodeId).
Result("id", "clusterId", "secondaryClusterIds", "groupId", "level").
Find()
if err != nil || one == nil {
return nil, err
}
var node = one.(*Node)
if node.Level < 1 {
node.Level = 1
}
return node, nil
}
// FindEnabledAndOnNodeClusterIds 获取节点所属所有可用而且启用的集群ID
func (this *NodeDAO) FindEnabledAndOnNodeClusterIds(tx *dbs.Tx, nodeId int64) (result []int64, err error) {
one, err := this.Query(tx).
@@ -474,6 +537,41 @@ func (this *NodeDAO) FindEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId int64
return result, nil
}
// FindEnabledNodesWithGroupIdAndLevel 查找当前分组下的某个级别的所有节点
func (this *NodeDAO) FindEnabledNodesWithGroupIdAndLevel(tx *dbs.Tx, groupId int64, level int) (result []*Node, err error) {
if groupId <= 0 {
return
}
_, err = this.Query(tx).
State(NodeStateEnabled).
Result("id", "clusterId", "secondaryClusterIds", "uniqueId", "secret").
Attr("isOn", true).
Attr("groupId", groupId).
Attr("level", level).
Slice(&result).
FindAll()
return
}
// FindEnabledNodesWithClusterIdAndLevel 查找当前集群下的某个级别的所有节点
func (this *NodeDAO) FindEnabledNodesWithClusterIdAndLevel(tx *dbs.Tx, clusterId int64, level int) (result []*Node, err error) {
if clusterId <= 0 {
return
}
_, err = this.Query(tx).
State(NodeStateEnabled).
Result("id", "clusterId", "secondaryClusterIds", "uniqueId", "secret").
Attr("isOn", true).
Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
Param("primaryClusterId", clusterId).
Param("primaryClusterIdString", types.String(clusterId)).
Attr("groupId", 0). // 需要去掉已经有分组的
Attr("level", level).
Slice(&result).
FindAll()
return
}
// FindAllNodeIdsMatch 匹配节点并返回节点ID
func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, includeSecondaryNodes bool, isOn configutils.BoolState) (result []int64, err error) {
var query = this.Query(tx)
@@ -555,6 +653,7 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
keyword string,
groupId int64,
regionId int64,
level int32,
includeSecondaryNodes bool) (int64, error) {
query := this.Query(tx)
query.State(NodeStateEnabled)
@@ -608,6 +707,11 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
query.Attr("regionId", regionId)
}
// 级别
if level > 0 {
query.Attr("level", level)
}
return query.Count()
}
@@ -733,6 +837,10 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
return nil, errors.New("node not found '" + strconv.FormatInt(nodeId, 10) + "'")
}
if node.Level < 1 {
node.Level = 1
}
var config = &nodeconfigs.NodeConfig{
Id: int64(node.Id),
NodeId: node.UniqueId,
@@ -743,6 +851,8 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
Name: node.Name,
MaxCPU: types.Int32(node.MaxCPU),
RegionId: int64(node.RegionId),
Level: types.Int32(node.Level),
GroupId: int64(node.GroupId),
}
// API节点IP
@@ -968,7 +1078,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
config.OCSPVersion = ocspVersion
// 初始化扩展配置
err = this.composeExtConfig(tx, config, cacheMap)
err = this.composeExtConfig(tx, config, clusterIds, cacheMap)
if err != nil {
return nil, err
}
@@ -1509,19 +1619,99 @@ func (this *NodeDAO) TransferPrimaryClusterNodes(tx *dbs.Tx, primaryClusterId in
return nil
}
// NotifyUpdate 通知更新
// FindParentNodeConfigs 查找父级节点配置
func (this *NodeDAO) FindParentNodeConfigs(tx *dbs.Tx, nodeId int64, groupId int64, clusterIds []int64, level int) (result map[int64][]*nodeconfigs.ParentNodeConfig, err error) {
result = map[int64][]*nodeconfigs.ParentNodeConfig{} // clusterId => []*ParentNodeConfig
// 当前分组的L2
var parentNodes []*Node
if groupId > 0 {
parentNodes, err = this.FindEnabledNodesWithGroupIdAndLevel(tx, groupId, level+1)
if err != nil {
return nil, err
}
}
// 当前集群的L2
if len(parentNodes) == 0 {
for _, clusterId := range clusterIds {
clusterParentNodes, err := this.FindEnabledNodesWithClusterIdAndLevel(tx, clusterId, level+1)
if err != nil {
return nil, err
}
if len(clusterParentNodes) > 0 {
parentNodes = append(parentNodes, clusterParentNodes...)
}
}
}
if len(parentNodes) > 0 {
for _, node := range parentNodes {
addrs, err := SharedNodeIPAddressDAO.FindAllEnabledAddressesWithNode(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
if err != nil {
return nil, err
}
var addrStrings = []string{}
for _, addr := range addrs {
if addr.IsOn {
addrStrings = append(addrStrings, addr.DNSIP())
}
}
// 没有地址就跳过
if len(addrStrings) == 0 {
continue
}
var secretHash = fmt.Sprintf("%x", sha256.Sum256([]byte(node.UniqueId+"@"+node.Secret)))
for _, clusterId := range node.AllClusterIds() {
parentNodeConfigs, _ := result[clusterId]
parentNodeConfigs = append(parentNodeConfigs, &nodeconfigs.ParentNodeConfig{
Id: int64(node.Id),
Addrs: addrStrings,
SecretHash: secretHash,
})
result[clusterId] = parentNodeConfigs
}
}
}
return
}
// NotifyUpdate 通知节点相关更新
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
clusterId, err := this.FindNodeClusterId(tx, nodeId)
if err != nil {
return err
}
if clusterId > 0 {
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeConfigChanged, 0)
err = SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeConfigChanged, 0)
if err != nil {
return err
}
return nil
}
// NotifyLevelUpdate 通知节点级别更新
func (this *NodeDAO) NotifyLevelUpdate(tx *dbs.Tx, nodeId int64) error {
// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
clusterIds, err := this.FindEnabledAndOnNodeClusterIds(tx, nodeId)
if err != nil {
return err
}
for _, clusterId := range clusterIds {
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeNodeLevelChanged)
if err != nil {
return err
}
}
return nil
}
// NotifyDNSUpdate 通知DNS更新
// NotifyDNSUpdate 通知节点相关DNS更新
func (this *NodeDAO) NotifyDNSUpdate(tx *dbs.Tx, nodeId int64) error {
clusterIds, err := this.FindEnabledAndOnNodeClusterIds(tx, nodeId)
if err != nil {

View File

@@ -10,6 +10,6 @@ import (
"github.com/iwind/TeaGo/dbs"
)
func (this *NodeDAO) composeExtConfig(tx *dbs.Tx, config *nodeconfigs.NodeConfig, cacheMap *utils.CacheMap) error {
func (this *NodeDAO) composeExtConfig(tx *dbs.Tx, config *nodeconfigs.NodeConfig, clusterIds []int64, cacheMap *utils.CacheMap) error {
return nil
}

View File

@@ -1,16 +1,23 @@
package models
//go:build plus
// +build plus
package models_test
import (
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/logs"
"testing"
"time"
)
func TestNodeDAO_FindAllNodeIdsMatch(t *testing.T) {
var tx *dbs.Tx
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, 1, true, 0)
dbs.NotifyReady()
nodeIds, err := models.SharedNodeDAO.FindAllNodeIdsMatch(tx, 1, true, 0)
if err != nil {
t.Fatal(err)
}
@@ -20,7 +27,7 @@ func TestNodeDAO_FindAllNodeIdsMatch(t *testing.T) {
func TestNodeDAO_UpdateNodeUp(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
err := SharedNodeDAO.UpdateNodeUp(tx, 57, false)
err := models.SharedNodeDAO.UpdateNodeUp(tx, 57, false)
if err != nil {
t.Fatal(err)
}
@@ -30,7 +37,7 @@ func TestNodeDAO_UpdateNodeUp(t *testing.T) {
func TestNodeDAO_FindEnabledNodeClusterIds(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
clusterIds, err := NewNodeDAO().FindEnabledAndOnNodeClusterIds(tx, 48)
clusterIds, err := models.NewNodeDAO().FindEnabledAndOnNodeClusterIds(tx, 48)
if err != nil {
t.Fatal(err)
}
@@ -47,7 +54,7 @@ func TestNodeDAO_ComposeNodeConfig(t *testing.T) {
var tx *dbs.Tx
var cacheMap = utils.NewCacheMap()
nodeConfig, err := SharedNodeDAO.ComposeNodeConfig(tx, 48, cacheMap)
nodeConfig, err := models.SharedNodeDAO.ComposeNodeConfig(tx, 48, cacheMap)
if err != nil {
t.Fatal(err)
}
@@ -56,3 +63,17 @@ func TestNodeDAO_ComposeNodeConfig(t *testing.T) {
// old: 77ms => new: 56ms
}
func TestNodeDAO_ComposeNodeConfig_ParentNodes(t *testing.T) {
dbs.NotifyReady()
teaconst.IsPlus = true
var tx *dbs.Tx
var cacheMap = utils.NewCacheMap()
nodeConfig, err := models.SharedNodeDAO.ComposeNodeConfig(tx, 48, cacheMap)
if err != nil {
t.Fatal(err)
}
logs.PrintAsJSON(nodeConfig.ParentNodes, t)
}

View File

@@ -540,9 +540,21 @@ func (this *NodeIPAddressDAO) NotifyUpdate(tx *dbs.Tx, addressId int64) error {
switch role {
case nodeconfigs.NodeRoleNode:
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, nodeId, dns.DNSTaskTypeNodeChange)
}
if err != nil {
return err
}
// 检查是否为L2以上级别
level, err := SharedNodeDAO.FindNodeLevel(tx, nodeId)
if err != nil {
return err
}
if level > 1 {
err = SharedNodeDAO.NotifyLevelUpdate(tx, nodeId)
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -7,6 +7,7 @@ type Node struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Level uint8 `field:"level"` // 级别
IsOn bool `field:"isOn"` // 是否启用
IsUp bool `field:"isUp"` // 是否在线
CountUp uint32 `field:"countUp"` // 连续在线次数
@@ -40,6 +41,7 @@ type NodeOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
Level interface{} // 级别
IsOn interface{} // 是否启用
IsUp interface{} // 是否在线
CountUp interface{} // 连续在线次数

View File

@@ -96,3 +96,15 @@ func (this *Node) DecodeSecondaryClusterIds() []int64 {
_ = json.Unmarshal(this.SecondaryClusterIds, &result)
return result
}
func (this *Node) AllClusterIds() []int64 {
var result = []int64{}
if this.ClusterId > 0 {
result = append(result, int64(this.ClusterId))
}
result = append(result, this.DecodeSecondaryClusterIds()...)
return result
}

View File

@@ -18,6 +18,7 @@ const (
NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged"
NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged"
NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged"
NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged"
// NS相关

View File

@@ -18,6 +18,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/andybalholm/brotli"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/types"
stringutil "github.com/iwind/TeaGo/utils/string"
@@ -164,7 +165,7 @@ func (this *NodeService) CountAllEnabledNodesMatch(ctx context.Context, req *pb.
tx := this.NullTx()
count, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, true)
count, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, req.Level, true)
if err != nil {
return nil, err
}
@@ -217,7 +218,7 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
order = "trafficOutDesc"
}
nodes, err := models.SharedNodeDAO.ListEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, true, order, req.Offset, req.Size)
nodes, err := models.SharedNodeDAO.ListEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, req.Level, true, order, req.Offset, req.Size)
if err != nil {
return nil, err
}
@@ -327,6 +328,7 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
NodeGroup: pbGroup,
NodeRegion: pbRegion,
DnsRoutes: pbRoutes,
Level: int32(node.Level),
})
}
@@ -423,7 +425,7 @@ func (this *NodeService) UpdateNode(ctx context.Context, req *pb.UpdateNodeReque
tx := this.NullTx()
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.SecondaryNodeClusterIds, req.NodeGroupId, req.NodeRegionId, req.IsOn)
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.SecondaryNodeClusterIds, req.NodeGroupId, req.NodeRegionId, req.IsOn, int(req.Level))
if err != nil {
return nil, err
}
@@ -579,6 +581,7 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
MaxCacheDiskCapacity: pbMaxCacheDiskCapacity,
MaxCacheMemoryCapacity: pbMaxCacheMemoryCapacity,
CacheDiskDir: node.CacheDiskDir,
Level: int32(node.Level),
}}, nil
}
@@ -608,6 +611,7 @@ func (this *NodeService) FindEnabledBasicNode(ctx context.Context, req *pb.FindE
Name: node.Name,
IsOn: node.IsOn,
IsUp: node.IsUp,
Level: int32(node.Level),
NodeCluster: &pb.NodeCluster{
Id: int64(node.ClusterId),
Name: clusterName,
@@ -994,7 +998,7 @@ func (this *NodeService) CountAllUpgradeNodesWithNodeClusterId(ctx context.Conte
tx := this.NullTx()
deployFiles := installers.SharedDeployManager.LoadNodeFiles()
var deployFiles = installers.SharedDeployManager.LoadNodeFiles()
total := int64(0)
for _, deployFile := range deployFiles {
count, err := models.SharedNodeDAO.CountAllLowerVersionNodesWithClusterId(tx, req.NodeClusterId, deployFile.OS, deployFile.Arch, deployFile.Version)
@@ -1616,3 +1620,38 @@ func (this *NodeService) findClusterCacheMap(clusterId int64, version int64) *ut
return cacheMap
}
}
// FindNodeLevelInfo 读取节点级别信息
func (this *NodeService) FindNodeLevelInfo(ctx context.Context, req *pb.FindNodeLevelInfoRequest) (*pb.FindNodeLevelInfoResponse, error) {
nodeId, err := this.ValidateNode(ctx)
if err != nil {
return nil, err
}
var tx *dbs.Tx
node, err := models.SharedNodeDAO.FindNodeLevelInfo(tx, nodeId)
if err != nil {
return nil, err
}
if node == nil {
return &pb.FindNodeLevelInfoResponse{}, nil
}
var result = &pb.FindNodeLevelInfoResponse{
Level: types.Int32(node.Level),
}
if node.Level == 1 {
parentNodes, err := models.SharedNodeDAO.FindParentNodeConfigs(tx, nodeId, int64(node.GroupId), node.AllClusterIds(), types.Int(node.Level))
if err != nil {
return nil, err
}
parentNodesJSON, err := json.Marshal(parentNodes)
if err != nil {
return nil, err
}
result.ParentNodesMapJSON = parentNodesJSON
}
return result, nil
}

View File

@@ -61,13 +61,13 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
var result = &pb.ComposeServerStatNodeClusterBoardResponse{}
// 统计数字
countActiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateYes, "", 0, 0, true)
countActiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateYes, "", 0, 0, 0, true)
if err != nil {
return nil, err
}
result.CountActiveNodes = countActiveNodes
countInactiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateNo, "", 0, 0, true)
countInactiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateNo, "", 0, 0, 0, true)
if err != nil {
return nil, err
}

File diff suppressed because one or more lines are too long