2020-07-22 22:17:53 +08:00
package models
import (
2020-09-13 20:37:28 +08:00
"encoding/json"
2020-10-04 14:27:14 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/errors"
2020-09-26 08:06:40 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
2020-07-22 22:17:53 +08:00
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
2020-10-25 21:27:46 +08:00
"github.com/iwind/TeaGo/maps"
2020-07-24 09:17:48 +08:00
"github.com/iwind/TeaGo/rands"
"github.com/iwind/TeaGo/types"
2020-09-26 08:06:40 +08:00
"strconv"
2020-07-22 22:17:53 +08:00
)
const (
NodeStateEnabled = 1 // 已启用
NodeStateDisabled = 0 // 已禁用
)
type NodeDAO dbs . DAO
func NewNodeDAO ( ) * NodeDAO {
return dbs . NewDAO ( & NodeDAO {
DAOObject : dbs . DAOObject {
DB : Tea . Env ,
Table : "edgeNodes" ,
Model : new ( Node ) ,
PkName : "id" ,
} ,
} ) . ( * NodeDAO )
}
2020-10-13 20:05:13 +08:00
var SharedNodeDAO * NodeDAO
func init ( ) {
dbs . OnReady ( func ( ) {
SharedNodeDAO = NewNodeDAO ( )
} )
}
2020-07-22 22:17:53 +08:00
// 启用条目
func ( this * NodeDAO ) EnableNode ( id uint32 ) ( rowsAffected int64 , err error ) {
return this . Query ( ) .
Pk ( id ) .
Set ( "state" , NodeStateEnabled ) .
Update ( )
}
// 禁用条目
2020-07-30 22:41:49 +08:00
func ( this * NodeDAO ) DisableNode ( id int64 ) ( err error ) {
_ , err = this . Query ( ) .
2020-07-22 22:17:53 +08:00
Pk ( id ) .
Set ( "state" , NodeStateDisabled ) .
Update ( )
2020-07-30 22:41:49 +08:00
return err
2020-07-22 22:17:53 +08:00
}
// 查找启用中的条目
2020-07-30 22:41:49 +08:00
func ( this * NodeDAO ) FindEnabledNode ( id int64 ) ( * Node , error ) {
2020-07-22 22:17:53 +08:00
result , err := this . Query ( ) .
Pk ( id ) .
Attr ( "state" , NodeStateEnabled ) .
Find ( )
if result == nil {
return nil , err
}
return result . ( * Node ) , err
}
// 根据主键查找名称
func ( this * NodeDAO ) FindNodeName ( id uint32 ) ( string , error ) {
name , err := this . Query ( ) .
Pk ( id ) .
Result ( "name" ) .
FindCol ( "" )
return name . ( string ) , err
}
2020-07-24 09:17:48 +08:00
// 创建节点
2020-07-30 22:41:49 +08:00
func ( this * NodeDAO ) CreateNode ( name string , clusterId int64 ) ( nodeId int64 , err error ) {
2020-08-21 12:32:33 +08:00
uniqueId , err := this . genUniqueId ( )
if err != nil {
return 0 , err
}
2020-09-06 16:19:54 +08:00
secret := rands . String ( 32 )
// 保存API Token
err = SharedApiTokenDAO . CreateAPIToken ( uniqueId , secret , NodeRoleNode )
if err != nil {
return
}
2020-07-24 09:17:48 +08:00
op := NewNodeOperator ( )
op . Name = name
2020-08-21 12:32:33 +08:00
op . UniqueId = uniqueId
2020-09-06 16:19:54 +08:00
op . Secret = secret
2020-07-24 09:17:48 +08:00
op . ClusterId = clusterId
2020-07-29 19:02:28 +08:00
op . IsOn = 1
2020-07-24 09:17:48 +08:00
op . State = NodeStateEnabled
_ , err = this . Save ( op )
if err != nil {
return 0 , err
}
2020-07-30 22:41:49 +08:00
return types . Int64 ( op . Id ) , nil
2020-07-24 09:17:48 +08:00
}
// 修改节点
2020-10-10 12:31:55 +08:00
func ( this * NodeDAO ) UpdateNode ( nodeId int64 , name string , clusterId int64 , maxCPU int32 , isOn bool ) error {
2020-07-30 22:41:49 +08:00
if nodeId <= 0 {
return errors . New ( "invalid nodeId" )
}
2020-07-24 09:17:48 +08:00
op := NewNodeOperator ( )
op . Id = nodeId
op . Name = name
op . ClusterId = clusterId
2020-08-21 12:32:33 +08:00
op . LatestVersion = dbs . SQL ( "latestVersion+1" )
2020-10-10 12:31:55 +08:00
op . MaxCPU = maxCPU
op . IsOn = isOn
2020-08-21 12:32:33 +08:00
_ , err := this . Save ( op )
return err
}
// 更新节点版本
func ( this * NodeDAO ) UpdateNodeLatestVersion ( nodeId int64 ) error {
if nodeId <= 0 {
return errors . New ( "invalid nodeId" )
}
op := NewNodeOperator ( )
op . Id = nodeId
op . LatestVersion = dbs . SQL ( "latestVersion+1" )
2020-07-24 09:17:48 +08:00
_ , err := this . Save ( op )
return err
}
2020-08-21 12:32:33 +08:00
// 批量更新节点版本
func ( this * NodeDAO ) UpdateAllNodesLatestVersionMatch ( clusterId int64 ) error {
nodeIds , err := this . FindAllNodeIdsMatch ( clusterId )
if err != nil {
return err
}
if len ( nodeIds ) == 0 {
return nil
}
_ , err = this . Query ( ) .
Pk ( nodeIds ) .
Set ( "latestVersion" , dbs . SQL ( "latestVersion+1" ) ) .
Update ( )
return err
}
// 同步集群中的节点版本
func ( this * NodeDAO ) SyncNodeVersionsWithCluster ( clusterId int64 ) error {
if clusterId <= 0 {
return errors . New ( "invalid cluster" )
}
_ , err := this . Query ( ) .
Attr ( "clusterId" , clusterId ) .
Set ( "version" , dbs . SQL ( "latestVersion" ) ) .
Update ( )
return err
}
// 取得有变更的集群
func ( this * NodeDAO ) FindChangedClusterIds ( ) ( [ ] int64 , error ) {
ones , _ , err := this . Query ( ) .
State ( NodeStateEnabled ) .
Gt ( "latestVersion" , 0 ) .
Where ( "version!=latestVersion" ) .
Result ( "DISTINCT(clusterId) AS clusterId" ) .
FindOnes ( )
if err != nil {
return nil , err
}
result := [ ] int64 { }
for _ , one := range ones {
result = append ( result , one . GetInt64 ( "clusterId" ) )
}
return result , nil
}
2020-07-24 09:17:48 +08:00
// 计算所有节点数量
func ( this * NodeDAO ) CountAllEnabledNodes ( ) ( int64 , error ) {
return this . Query ( ) .
State ( NodeStateEnabled ) .
Count ( )
}
// 列出单页节点
2020-09-26 08:06:40 +08:00
func ( this * NodeDAO ) ListEnabledNodesMatch ( offset int64 , size int64 , clusterId int64 , installState configutils . BoolState , activeState configutils . BoolState ) ( result [ ] * Node , err error ) {
2020-08-30 16:12:00 +08:00
query := this . Query ( ) .
2020-07-24 09:17:48 +08:00
State ( NodeStateEnabled ) .
2020-07-29 19:02:28 +08:00
Offset ( offset ) .
Limit ( size ) .
2020-07-24 09:17:48 +08:00
DescPk ( ) .
2020-08-30 16:12:00 +08:00
Slice ( & result )
2020-09-13 20:37:28 +08:00
// 集群
2020-08-30 16:12:00 +08:00
if clusterId > 0 {
query . Attr ( "clusterId" , clusterId )
}
2020-09-13 20:37:28 +08:00
// 安装状态
switch installState {
2020-09-26 08:06:40 +08:00
case configutils . BoolStateAll :
// 所有
case configutils . BoolStateYes :
2020-09-13 20:37:28 +08:00
query . Attr ( "isInstalled" , 1 )
2020-09-26 08:06:40 +08:00
case configutils . BoolStateNo :
2020-09-13 20:37:28 +08:00
query . Attr ( "isInstalled" , 0 )
}
2020-09-26 08:06:40 +08:00
// 在线状态
switch activeState {
case configutils . BoolStateAll :
// 所有
case configutils . BoolStateYes :
2020-09-28 16:25:39 +08:00
query . Where ( "JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60" )
2020-09-26 08:06:40 +08:00
case configutils . BoolStateNo :
2020-09-28 16:25:39 +08:00
query . Where ( "(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)" )
2020-09-26 08:06:40 +08:00
}
2020-08-30 16:12:00 +08:00
_ , err = query . FindAll ( )
2020-07-24 09:17:48 +08:00
return
}
2020-08-21 12:32:33 +08:00
// 根据节点ID和密钥查询节点
func ( this * NodeDAO ) FindEnabledNodeWithUniqueIdAndSecret ( uniqueId string , secret string ) ( * Node , error ) {
one , err := this . Query ( ) .
Attr ( "uniqueId" , uniqueId ) .
Attr ( "secret" , secret ) .
State ( NodeStateEnabled ) .
Find ( )
if one != nil {
return one . ( * Node ) , err
}
return nil , err
}
// 根据节点ID获取节点
func ( this * NodeDAO ) FindEnabledNodeWithUniqueId ( uniqueId string ) ( * Node , error ) {
one , err := this . Query ( ) .
Attr ( "uniqueId" , uniqueId ) .
State ( NodeStateEnabled ) .
Find ( )
if one != nil {
return one . ( * Node ) , err
}
return nil , err
}
// 获取节点集群ID
func ( this * NodeDAO ) FindNodeClusterId ( nodeId int64 ) ( int64 , error ) {
col , err := this . Query ( ) .
Pk ( nodeId ) .
Result ( "clusterId" ) .
FindCol ( 0 )
return types . Int64 ( col ) , err
}
// 匹配节点并返回节点ID
func ( this * NodeDAO ) FindAllNodeIdsMatch ( clusterId int64 ) ( result [ ] int64 , err error ) {
query := this . Query ( )
query . State ( NodeStateEnabled )
if clusterId > 0 {
query . Attr ( "clusterId" , clusterId )
}
query . Result ( "id" )
ones , _ , err := query . FindOnes ( )
if err != nil {
return nil , err
}
for _ , one := range ones {
result = append ( result , one . GetInt64 ( "id" ) )
}
return
}
2020-10-04 14:27:14 +08:00
// 获取一个集群的所有节点
func ( this * NodeDAO ) FindAllEnabledNodesWithClusterId ( clusterId int64 ) ( result [ ] * Node , err error ) {
_ , err = this . Query ( ) .
State ( NodeStateEnabled ) .
Attr ( "clusterId" , clusterId ) .
DescPk ( ) .
Slice ( & result ) .
FindAll ( )
return
}
2020-10-25 18:26:46 +08:00
// 取得一个集群离线的节点
func ( this * NodeDAO ) FindAllInactiveNodesWithClusterId ( clusterId int64 ) ( result [ ] * Node , err error ) {
_ , err = this . Query ( ) .
State ( NodeStateEnabled ) .
Attr ( "clusterId" , clusterId ) .
Attr ( "isOn" , true ) . // 只监控启用的节点
2020-10-25 21:27:46 +08:00
Attr ( "isInstalled" , true ) . // 只监控已经安装的节点
2020-10-25 18:26:46 +08:00
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)" ) .
Slice ( & result ) .
FindAll ( )
return
}
2020-08-30 16:12:00 +08:00
// 计算节点数量
2020-09-26 08:06:40 +08:00
func ( this * NodeDAO ) CountAllEnabledNodesMatch ( clusterId int64 , installState configutils . BoolState , activeState configutils . BoolState ) ( int64 , error ) {
2020-08-30 16:12:00 +08:00
query := this . Query ( )
query . State ( NodeStateEnabled )
2020-09-13 20:37:28 +08:00
// 集群
2020-08-30 16:12:00 +08:00
if clusterId > 0 {
query . Attr ( "clusterId" , clusterId )
}
2020-09-13 20:37:28 +08:00
// 安装状态
switch installState {
2020-09-26 08:06:40 +08:00
case configutils . BoolStateAll :
// 所有
case configutils . BoolStateYes :
2020-09-13 20:37:28 +08:00
query . Attr ( "isInstalled" , 1 )
2020-09-26 08:06:40 +08:00
case configutils . BoolStateNo :
2020-09-13 20:37:28 +08:00
query . Attr ( "isInstalled" , 0 )
}
2020-09-26 08:06:40 +08:00
// 在线状态
switch activeState {
case configutils . BoolStateAll :
// 所有
case configutils . BoolStateYes :
2020-09-28 16:25:39 +08:00
query . Where ( "JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60" )
2020-09-26 08:06:40 +08:00
case configutils . BoolStateNo :
2020-09-28 16:25:39 +08:00
query . Where ( "(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)" )
2020-09-26 08:06:40 +08:00
}
2020-08-30 16:12:00 +08:00
return query . Count ( )
}
2020-08-21 12:32:33 +08:00
// 更改节点状态
func ( this * NodeDAO ) UpdateNodeStatus ( nodeId int64 , statusJSON [ ] byte ) error {
_ , err := this . Query ( ) .
Pk ( nodeId ) .
Set ( "status" , string ( statusJSON ) ) .
Update ( )
return err
}
2020-10-25 18:26:46 +08:00
// 更改节点在线状态
func ( this * NodeDAO ) UpdateNodeIsActive ( nodeId int64 , isActive bool ) error {
b := "true"
if ! isActive {
b = "false"
}
_ , err := this . Query ( ) .
Pk ( nodeId ) .
Where ( "status IS NOT NULL" ) .
Set ( "status" , dbs . SQL ( "JSON_SET(status, '$.isActive', " + b + ")" ) ) .
Update ( )
return err
}
2020-09-06 16:19:54 +08:00
// 设置节点安装状态
func ( this * NodeDAO ) UpdateNodeIsInstalled ( nodeId int64 , isInstalled bool ) error {
_ , err := this . Query ( ) .
Pk ( nodeId ) .
Set ( "isInstalled" , isInstalled ) .
2020-09-13 20:37:28 +08:00
Set ( "installStatus" , "null" ) . // 重置安装状态
Update ( )
return err
}
// 查询节点的安装状态
func ( this * NodeDAO ) FindNodeInstallStatus ( nodeId int64 ) ( * NodeInstallStatus , error ) {
2020-10-26 21:14:56 +08:00
node , err := this . Query ( ) .
2020-09-13 20:37:28 +08:00
Pk ( nodeId ) .
2020-10-26 21:14:56 +08:00
Result ( "installStatus" , "isInstalled" ) .
Find ( )
2020-09-13 20:37:28 +08:00
if err != nil {
return nil , err
}
2020-10-26 21:14:56 +08:00
if node == nil {
return nil , errors . New ( "not found" )
}
2020-09-13 20:37:28 +08:00
2020-10-26 21:14:56 +08:00
installStatus := node . ( * Node ) . InstallStatus
isInstalled := node . ( * Node ) . IsInstalled == 1
2020-09-13 20:37:28 +08:00
if len ( installStatus ) == 0 {
return NewNodeInstallStatus ( ) , nil
}
status := & NodeInstallStatus { }
err = json . Unmarshal ( [ ] byte ( installStatus ) , status )
2020-10-26 21:14:56 +08:00
if err != nil {
return nil , err
}
if isInstalled {
status . IsFinished = true
status . IsOk = true
}
return status , nil
2020-09-13 20:37:28 +08:00
}
// 修改节点的安装状态
func ( this * NodeDAO ) UpdateNodeInstallStatus ( nodeId int64 , status * NodeInstallStatus ) error {
if status == nil {
_ , err := this . Query ( ) .
Pk ( nodeId ) .
Set ( "installStatus" , "null" ) .
Update ( )
return err
}
data , err := json . Marshal ( status )
if err != nil {
return err
}
_ , err = this . Query ( ) .
Pk ( nodeId ) .
Set ( "installStatus" , string ( data ) ) .
2020-09-06 16:19:54 +08:00
Update ( )
return err
}
2020-09-26 08:06:40 +08:00
// 组合配置
func ( this * NodeDAO ) ComposeNodeConfig ( nodeId int64 ) ( * nodeconfigs . NodeConfig , error ) {
node , err := this . FindEnabledNode ( nodeId )
if err != nil {
return nil , err
}
if node == nil {
return nil , errors . New ( "node not found '" + strconv . FormatInt ( nodeId , 10 ) + "'" )
}
config := & nodeconfigs . NodeConfig {
2020-10-09 11:06:37 +08:00
Id : int64 ( node . Id ) ,
NodeId : node . UniqueId ,
2020-09-26 08:06:40 +08:00
IsOn : node . IsOn == 1 ,
Servers : nil ,
Version : int64 ( node . Version ) ,
Name : node . Name ,
2020-10-10 12:31:55 +08:00
MaxCPU : types . Int32 ( node . MaxCPU ) ,
2020-09-26 08:06:40 +08:00
}
// 获取所有的服务
servers , err := SharedServerDAO . FindAllEnabledServersWithNode ( int64 ( node . Id ) )
if err != nil {
return nil , err
}
for _ , server := range servers {
if len ( server . Config ) == 0 {
continue
}
serverConfig := & serverconfigs . ServerConfig { }
err = json . Unmarshal ( [ ] byte ( server . Config ) , serverConfig )
if err != nil {
return nil , err
}
config . Servers = append ( config . Servers , serverConfig )
}
// 全局设置
// TODO 根据用户的不同读取不同的全局设置
settingJSON , err := SharedSysSettingDAO . ReadSetting ( SettingCodeGlobalConfig )
if err != nil {
return nil , err
}
if len ( settingJSON ) > 0 {
globalConfig := & serverconfigs . GlobalConfig { }
err = json . Unmarshal ( settingJSON , globalConfig )
if err != nil {
return nil , err
}
config . GlobalConfig = globalConfig
}
return config , nil
}
2020-10-04 14:27:14 +08:00
// 修改当前连接的API节点
func ( this * NodeDAO ) UpdateNodeConnectedAPINodes ( nodeId int64 , apiNodeIds [ ] int64 ) error {
if nodeId <= 0 {
return errors . New ( "invalid nodeId" )
}
op := NewNodeOperator ( )
op . Id = nodeId
if len ( apiNodeIds ) > 0 {
apiNodeIdsJSON , err := json . Marshal ( apiNodeIds )
if err != nil {
return errors . Wrap ( err )
}
op . ConnectedAPINodes = apiNodeIdsJSON
} else {
op . ConnectedAPINodes = "[]"
}
_ , err := this . Save ( op )
return err
}
2020-10-14 18:44:34 +08:00
// 根据UniqueId获取ID
// TODO 增加缓存
func ( this * NodeDAO ) FindEnabledNodeIdWithUniqueId ( uniqueId string ) ( int64 , error ) {
return this . Query ( ) .
State ( NodeStateEnabled ) .
Attr ( "uniqueId" , uniqueId ) .
ResultPk ( ) .
FindInt64Col ( 0 )
}
2020-10-25 21:27:46 +08:00
// 计算使用某个认证的节点数量
func ( this * NodeDAO ) CountAllEnabledNodesWithGrantId ( grantId int64 ) ( int64 , error ) {
return this . Query ( ) .
State ( NodeStateEnabled ) .
Where ( "id IN (SELECT nodeId FROM edgeNodeLogins WHERE type='ssh' AND JSON_CONTAINS(params, :grantParam))" ) .
Param ( "grantParam" , string ( maps . Map { "grantId" : grantId } . AsJSON ( ) ) ) .
Count ( )
}
// 查找使用某个认证的所有节点
func ( this * NodeDAO ) FindAllEnabledNodesWithGrantId ( grantId int64 ) ( result [ ] * Node , err error ) {
_ , err = this . Query ( ) .
State ( NodeStateEnabled ) .
Where ( "id IN (SELECT nodeId FROM edgeNodeLogins WHERE type='ssh' AND JSON_CONTAINS(params, :grantParam))" ) .
Param ( "grantParam" , string ( maps . Map { "grantId" : grantId } . AsJSON ( ) ) ) .
Slice ( & result ) .
DescPk ( ) .
FindAll ( )
return
}
2020-10-26 21:14:56 +08:00
// 查找所有未安装的节点
func ( this * NodeDAO ) FindAllNotInstalledNodesWithClusterId ( clusterId int64 ) ( result [ ] * Node , err error ) {
_ , err = this . Query ( ) .
State ( NodeStateEnabled ) .
Attr ( "clusterId" , clusterId ) .
Attr ( "isInstalled" , false ) .
DescPk ( ) .
Slice ( & result ) .
FindAll ( )
return
}
2020-08-21 12:32:33 +08:00
// 生成唯一ID
func ( this * NodeDAO ) genUniqueId ( ) ( string , error ) {
for {
uniqueId := rands . HexString ( 32 )
ok , err := this . Query ( ) .
Attr ( "uniqueId" , uniqueId ) .
Exist ( )
if err != nil {
return "" , err
}
if ok {
continue
}
return uniqueId , nil
}
}