实现最基本的域名服务节点管理

This commit is contained in:
GoEdgeLab
2021-05-26 14:43:29 +08:00
parent fa3a0e6f59
commit 04db86a919
58 changed files with 1574 additions and 57 deletions

View File

@@ -356,6 +356,10 @@ func (this *RPCClient) NSClusterRPC() pb.NSClusterServiceClient {
return pb.NewNSClusterServiceClient(this.pickConn())
}
func (this *RPCClient) NSNodeRPC() pb.NSNodeServiceClient {
return pb.NewNSNodeServiceClient(this.pickConn())
}
// Context 构造Admin上下文
func (this *RPCClient) Context(adminId int64) context.Context {
ctx := context.Background()

View File

@@ -20,7 +20,7 @@ type ParentAction struct {
rpcClient *rpc.RPCClient
}
// 可以调用自身的一个简便方法
// Parent 可以调用自身的一个简便方法
func (this *ParentAction) Parent() *ParentAction {
return this
}
@@ -97,7 +97,7 @@ func (this *ParentAction) CreateLogInfo(description string, args ...interface{})
this.CreateLog(oplogs.LevelInfo, description, args...)
}
// 获取RPC
// RPC 获取RPC
func (this *ParentAction) RPC() *rpc.RPCClient {
if this.rpcClient != nil {
return this.rpcClient
@@ -114,7 +114,7 @@ func (this *ParentAction) RPC() *rpc.RPCClient {
return rpcClient
}
// 获取Context
// AdminContext 获取Context
func (this *ParentAction) AdminContext() context.Context {
if this.rpcClient == nil {
rpcClient, err := rpc.SharedRPC()

View File

@@ -13,15 +13,15 @@ import (
"strings"
)
// 提示服务器错误信息
// Fail 提示服务器错误信息
func Fail(action actions.ActionWrapper, err error) {
if err != nil {
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
}
action.Object().Fail(teaconst.ErrServer)
action.Object().Fail(teaconst.ErrServer + "" + err.Error() + "")
}
// 提示页面错误信息
// FailPage 提示页面错误信息
func FailPage(action actions.ActionWrapper, err error) {
if err != nil {
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
@@ -43,12 +43,12 @@ func FailPage(action actions.ActionWrapper, err error) {
}
}
// 判断动作的文件路径是否相当
// MatchPath 判断动作的文件路径是否相当
func MatchPath(action *actions.ActionObject, path string) bool {
return action.Request.URL.Path == path
}
// 查找父级Action
// FindParentAction 查找父级Action
func FindParentAction(actionPtr actions.ActionWrapper) *ParentAction {
parentActionValue := reflect.ValueOf(actionPtr).Elem().FieldByName("ParentAction")
if parentActionValue.IsValid() {

View File

@@ -3,6 +3,7 @@ package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
@@ -90,6 +91,7 @@ func (this *CreateBatchAction) RunPost(params struct {
nodeId := resp.NodeId
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleNode,
Name: "IP地址",
Ip: ip,
CanAccess: true,

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
@@ -156,6 +157,7 @@ func (this *CreateNodeAction) RunPost(params struct {
} else {
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleNode,
Name: address.GetString("name"),
Ip: address.GetString("ip"),
CanAccess: address.GetBool("canAccess"),

View File

@@ -71,6 +71,10 @@ func (this *IndexAction) RunGet(params struct {
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeMaps := []maps.Map{}
for _, node := range nodesResp.Nodes {
// 状态
@@ -87,7 +91,10 @@ func (this *IndexAction) RunGet(params struct {
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: node.Id})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -30,7 +30,7 @@ func init() {
GetPost("/installManual", new(InstallManualAction)).
// 节点相关
Get("/node", new(node.NodeAction)).
Get("/node", new(node.IndexAction)).
GetPost("/node/update", new(node.UpdateAction)).
GetPost("/node/install", new(node.InstallAction)).
Post("/node/updateInstallStatus", new(node.UpdateInstallStatusAction)).

View File

@@ -12,16 +12,16 @@ import (
"time"
)
type NodeAction struct {
type IndexAction struct {
actionutils.ParentAction
}
func (this *NodeAction) Init() {
func (this *IndexAction) Init() {
this.Nav("", "node", "node")
this.SecondMenu("nodes")
}
func (this *NodeAction) RunGet(params struct {
func (this *IndexAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
@@ -56,7 +56,10 @@ func (this *NodeAction) RunGet(params struct {
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -6,6 +6,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
@@ -46,7 +47,10 @@ func (this *UpdateAction) RunGet(params struct {
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
@@ -340,14 +344,17 @@ func (this *UpdateAction) RunPost(params struct {
}
// 禁用老的IP地址
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
}
// 添加新的IP地址
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, params.IPAddressesJSON)
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleNode, params.IPAddressesJSON)
if err != nil {
this.ErrorPage(err)
return

View File

@@ -186,7 +186,10 @@ func (this *IndexAction) searchNodes(keyword string) {
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: node.Id})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -1,7 +1,6 @@
package nodes
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
@@ -13,14 +12,14 @@ type DeleteAction struct {
func (this *DeleteAction) RunPost(params struct {
NodeId int64
}) {
// 创建日志
defer this.CreateLogInfo("删除节点", params.NodeId)
_, err := this.RPC().NodeRPC().DeleteNode(this.AdminContext(), &pb.DeleteNodeRequest{NodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "删除节点", params.NodeId)
this.Success()
}

View File

@@ -3,12 +3,13 @@ package ipaddressutils
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// 保存一组IP地址
func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64, ipAddressesJSON []byte) error {
// UpdateNodeIPAddresses 保存一组IP地址
func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64, role nodeconfigs.NodeRole, ipAddressesJSON []byte) error {
addresses := []maps.Map{}
err := json.Unmarshal(ipAddressesJSON, &addresses)
if err != nil {
@@ -29,6 +30,7 @@ func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64,
} else {
_, err = parentAction.RPC().NodeIPAddressRPC().CreateNodeIPAddress(parentAction.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: role,
Name: addr.GetString("name"),
Ip: addr.GetString("ip"),
CanAccess: addr.GetBool("canAccess"),

View File

@@ -0,0 +1,100 @@
package cluster
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
// CreateNodeAction 创建节点
type CreateNodeAction struct {
actionutils.ParentAction
}
func (this *CreateNodeAction) Init() {
this.Nav("", "node", "create")
this.SecondMenu("nodes")
}
func (this *CreateNodeAction) RunGet(params struct {
ClusterId int64
}) {
this.Show()
}
func (this *CreateNodeAction) RunPost(params struct {
Name string
IpAddressesJSON []byte
ClusterId int64
Must *actions.Must
}) {
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
if len(params.IpAddressesJSON) == 0 {
this.Fail("请至少添加一个IP地址")
}
// TODO 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IpAddressesJSON) > 0 {
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// 保存
createResp, err := this.RPC().NSNodeRPC().CreateNSNode(this.AdminContext(), &pb.CreateNSNodeRequest{
Name: params.Name,
NodeClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeId := createResp.NsNodeId
// IP地址
for _, address := range ipAddresses {
addressId := address.GetInt64("id")
if addressId > 0 {
_, err = this.RPC().NodeIPAddressRPC().UpdateNodeIPAddressNodeId(this.AdminContext(), &pb.UpdateNodeIPAddressNodeIdRequest{
AddressId: addressId,
NodeId: nodeId,
})
} else {
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleDNS,
Name: address.GetString("name"),
Ip: address.GetString("ip"),
CanAccess: address.GetBool("canAccess"),
})
}
if err != nil {
this.ErrorPage(err)
return
}
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建域名服务节点 %d", nodeId)
this.Success()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteNodeAction struct {
actionutils.ParentAction
}
func (this *DeleteNodeAction) RunPost(params struct {
NodeId int64
}) {
defer this.CreateLogInfo("删除域名服务节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().DeleteNSNode(this.AdminContext(), &pb.DeleteNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -2,16 +2,138 @@
package cluster
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "")
this.Nav("", "node", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
func (this *IndexAction) RunGet(params struct {
ClusterId int64
InstalledState int
ActiveState int
Keyword string
}) {
this.Data["installState"] = params.InstalledState
this.Data["activeState"] = params.ActiveState
this.Data["keyword"] = params.Keyword
countAllResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countAll"] = countAllResp.Count
countResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
page := this.NewPage(countResp.Count)
this.Data["page"] = page.AsHTML()
nodesResp, err := this.RPC().NSNodeRPC().ListEnabledNSNodesMatch(this.AdminContext(), &pb.ListEnabledNSNodesMatchRequest{
Offset: page.Offset,
Size: page.Size,
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeMaps := []maps.Map{}
for _, node := range nodesResp.NsNodes {
// 状态
status := &nodeconfigs.NodeStatus{}
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
logs.Error(err)
continue
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddresses := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddresses = append(ipAddresses, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
"isInstalled": node.IsInstalled,
"isOn": node.IsOn,
"isUp": node.IsUp,
"installStatus": maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"error": node.InstallStatus.Error,
},
"status": maps.Map{
"isActive": status.IsActive,
"updatedAt": status.UpdatedAt,
"hostname": status.Hostname,
"cpuUsage": status.CPUUsage,
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
},
"ipAddresses": ipAddresses,
})
}
this.Data["nodes"] = nodeMaps
// 记录最近访问
_, err = this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
ItemType: "nsCluster",
ItemId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Show()
}

View File

@@ -2,6 +2,7 @@ package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/node"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
@@ -17,6 +18,18 @@ func init() {
Prefix("/ns/clusters/cluster").
Get("", new(IndexAction)).
GetPost("/delete", new(DeleteAction)).
GetPost("/createNode", new(CreateNodeAction)).
Post("/deleteNode", new(DeleteNodeAction)).
// 节点相关
Prefix("/ns/clusters/cluster/node").
Get("", new(node.IndexAction)).
Get("/logs", new(node.LogsAction)).
GetPost("/update", new(node.UpdateAction)).
GetPost("/install", new(node.InstallAction)).
Post("/status", new(node.StatusAction)).
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
EndAll()
})
}

View File

@@ -0,0 +1,137 @@
package node
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "node")
this.SecondMenu("nodes")
}
func (this *IndexAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NsCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
// 运行状态
status := &nodeconfigs.NodeStatus{}
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
this.ErrorPage(err)
return
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
// 检查是否有新版本
if len(status.OS) > 0 {
checkVersionResp, err := this.RPC().NodeRPC().CheckNodeLatestVersion(this.AdminContext(), &pb.CheckNodeLatestVersionRequest{
Os: status.OS,
Arch: status.Arch,
CurrentVersion: status.BuildVersion,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["shouldUpgrade"] = checkVersionResp.HasNewVersion
this.Data["newVersion"] = checkVersionResp.NewVersion
} else {
this.Data["shouldUpgrade"] = false
this.Data["newVersion"] = ""
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"isOn": node.IsOn,
"status": maps.Map{
"isActive": status.IsActive,
"updatedAt": status.UpdatedAt,
"hostname": status.Hostname,
"cpuUsage": status.CPUUsage,
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
"connectionCount": status.ConnectionCount,
"buildVersion": status.BuildVersion,
"cpuPhysicalCount": status.CPUPhysicalCount,
"cpuLogicalCount": status.CPULogicalCount,
"load1m": fmt.Sprintf("%.2f", status.Load1m),
"load5m": fmt.Sprintf("%.2f", status.Load5m),
"load15m": fmt.Sprintf("%.2f", status.Load15m),
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
},
}
this.Show()
}

View File

@@ -0,0 +1,117 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
// InstallAction 安装节点
type InstallAction struct {
actionutils.ParentAction
}
func (this *InstallAction) Init() {
this.Nav("", "node", "install")
this.SecondMenu("nodes")
}
func (this *InstallAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
}
} else {
this.Data["installStatus"] = nil
}
// 集群
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NodeCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// API节点列表
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
apiNodes := apiNodesResp.Nodes
apiEndpoints := []string{}
for _, apiNode := range apiNodes {
if !apiNode.IsOn {
continue
}
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
}
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"cluster": clusterMap,
}
this.Show()
}
// RunPost 开始安装
func (this *InstallAction) RunPost(params struct {
NodeId int64
Must *actions.Must
}) {
// 创建日志
defer this.CreateLogInfo("安装节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().InstallNSNode(this.AdminContext(), &pb.InstallNSNodeRequest{
NsNodeId: params.NodeId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,75 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type LogsAction struct {
actionutils.ParentAction
}
func (this *LogsAction) Init() {
this.Nav("", "node", "log")
this.SecondMenu("nodes")
}
func (this *LogsAction) RunGet(params struct {
NodeId int64
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["nodeId"] = params.NodeId
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
Role: nodeconfigs.NodeRoleDNS,
NodeId: params.NodeId,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count, 20)
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})
logs := []maps.Map{}
for _, log := range logsResp.NodeLogs {
logs = append(logs, maps.Map{
"tag": log.Tag,
"description": log.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
"level": log.Level,
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
"count": log.Count,
})
}
this.Data["logs"] = logs
this.Data["page"] = page.AsHTML()
this.Show()
}

View File

@@ -0,0 +1,46 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// StatusAction 节点状态
type StatusAction struct {
actionutils.ParentAction
}
func (this *StatusAction) RunPost(params struct {
NodeId int64
}) {
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
"errorCode": node.InstallStatus.ErrorCode,
}
} else {
this.Data["installStatus"] = nil
}
this.Data["isInstalled"] = node.IsInstalled
this.Success()
}

View File

@@ -0,0 +1,164 @@
package node
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) Init() {
this.Nav("", "node", "update")
this.SecondMenu("nodes")
}
func (this *UpdateAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterMap = maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"isOn": node.IsOn,
}
// 所有集群
resp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
}
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range resp.NsClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
this.Show()
}
func (this *UpdateAction) RunPost(params struct {
LoginId int64
NodeId int64
Name string
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
ClusterId int64
IsOn bool
Must *actions.Must
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d", params.NodeId)
if params.NodeId <= 0 {
this.Fail("要操作的节点不存在")
}
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
// TODO 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IPAddressesJSON) > 0 {
err := json.Unmarshal(params.IPAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// 保存
_, err := this.RPC().NSNodeRPC().UpdateNSNode(this.AdminContext(), &pb.UpdateNSNodeRequest{
NsNodeId: params.NodeId,
Name: params.Name,
NsClusterId: params.ClusterId,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
// 禁用老的IP地址
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
// 添加新的IP地址
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleDNS, params.IPAddressesJSON)
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,30 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type UpdateInstallStatusAction struct {
actionutils.ParentAction
}
func (this *UpdateInstallStatusAction) RunPost(params struct {
NodeId int64
IsInstalled bool
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点安装状态 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().UpdateNSNodeIsInstalled(this.AdminContext(), &pb.UpdateNSNodeIsInstalledRequest{
NsNodeId: params.NodeId,
IsInstalled: params.IsInstalled,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -4,8 +4,10 @@ package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -36,10 +38,37 @@ func (this *IndexAction) RunGet(params struct{}) {
}
clusterMaps := []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
// 全部节点数量
countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
// 在线节点
countActiveNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: cluster.Id,
ActiveState: types.Int32(configutils.BoolStateYes),
})
if err != nil {
this.ErrorPage(err)
return
}
// 需要升级的节点
countUpgradeNodesResp, err := this.RPC().NSNodeRPC().CountAllUpgradeNSNodesWithNSClusterId(this.AdminContext(), &pb.CountAllUpgradeNSNodesWithNSClusterIdRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
"countAllNodes": countNodesResp.Count,
"countActiveNodes": countActiveNodesResp.Count,
"countUpgradeNodes": countUpgradeNodesResp.Count,
})
}
this.Data["clusters"] = clusterMaps