diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go
index 87fa1a78..061cfbb4 100644
--- a/internal/rpc/rpc_client.go
+++ b/internal/rpc/rpc_client.go
@@ -139,6 +139,10 @@ func (this *RPCClient) DBNodeRPC() pb.DBNodeServiceClient {
return pb.NewDBNodeServiceClient(this.pickConn())
}
+func (this *RPCClient) MonitorNodeRPC() pb.MonitorNodeServiceClient {
+ return pb.NewMonitorNodeServiceClient(this.pickConn())
+}
+
func (this *RPCClient) DBRPC() pb.DBServiceClient {
return pb.NewDBServiceClient(this.pickConn())
}
diff --git a/internal/web/actions/default/settings/monitor-nodes/delete.go b/internal/web/actions/default/settings/monitor-nodes/delete.go
new file mode 100644
index 00000000..822d90c4
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/delete.go
@@ -0,0 +1,28 @@
+package monitornodes
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+)
+
+type DeleteAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DeleteAction) RunPost(params struct {
+ NodeId int64
+}) {
+ // TODO 检查权限
+
+ _, err := this.RPC().MonitorNodeRPC().DeleteMonitorNode(this.AdminContext(), &pb.DeleteMonitorNodeRequest{NodeId: params.NodeId})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ // 创建日志
+ defer this.CreateLog(oplogs.LevelInfo, "删除监控节点 %d", params.NodeId)
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/helper.go b/internal/web/actions/default/settings/monitor-nodes/helper.go
new file mode 100644
index 00000000..99fc7746
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/helper.go
@@ -0,0 +1,15 @@
+package monitornodes
+
+import (
+ "github.com/iwind/TeaGo/actions"
+)
+
+type Helper struct {
+}
+
+func NewHelper() *Helper {
+ return &Helper{}
+}
+
+func (this *Helper) BeforeAction(action *actions.ActionObject) {
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/index.go b/internal/web/actions/default/settings/monitor-nodes/index.go
new file mode 100644
index 00000000..d8b17d68
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/index.go
@@ -0,0 +1,75 @@
+package monitornodes
+
+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"
+ "time"
+)
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) Init() {
+ this.Nav("", "node", "index")
+}
+
+func (this *IndexAction) RunGet(params struct{}) {
+ countResp, err := this.RPC().MonitorNodeRPC().CountAllEnabledMonitorNodes(this.AdminContext(), &pb.CountAllEnabledMonitorNodesRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ count := countResp.Count
+ page := this.NewPage(count)
+ this.Data["page"] = page.AsHTML()
+
+ nodeMaps := []maps.Map{}
+ if count > 0 {
+ nodesResp, err := this.RPC().MonitorNodeRPC().ListEnabledMonitorNodes(this.AdminContext(), &pb.ListEnabledMonitorNodesRequest{
+ Offset: page.Offset,
+ Size: page.Size,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ for _, node := range nodesResp.Nodes {
+ // 状态
+ 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秒之内认为活跃
+ }
+
+ nodeMaps = append(nodeMaps, maps.Map{
+ "id": node.Id,
+ "isOn": node.IsOn,
+ "name": node.Name,
+ "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),
+ "buildVersion": status.BuildVersion,
+ },
+ })
+ }
+ }
+ this.Data["nodes"] = nodeMaps
+
+ this.Show()
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/init.go b/internal/web/actions/default/settings/monitor-nodes/init.go
new file mode 100644
index 00000000..fa97e80c
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/init.go
@@ -0,0 +1,23 @@
+package monitornodes
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/monitor-nodes/node"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
+ Helper(NewHelper()).
+ Helper(settingutils.NewAdvancedHelper("monitorNodes")).
+ Prefix("/settings/monitorNodes").
+ Get("", new(IndexAction)).
+ GetPost("/node/createPopup", new(node.CreatePopupAction)).
+ Post("/delete", new(DeleteAction)).
+ EndAll()
+ })
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/createPopup.go b/internal/web/actions/default/settings/monitor-nodes/node/createPopup.go
new file mode 100644
index 00000000..3ce8ee2f
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/createPopup.go
@@ -0,0 +1,47 @@
+package node
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/actions"
+)
+
+type CreatePopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CreatePopupAction) Init() {
+ this.Nav("", "node", "create")
+}
+
+func (this *CreatePopupAction) RunGet(params struct{}) {
+ this.Show()
+}
+
+func (this *CreatePopupAction) RunPost(params struct {
+ Name string
+ Description string
+ IsOn bool
+
+ Must *actions.Must
+}) {
+ params.Must.
+ Field("name", params.Name).
+ Require("请输入监控节点名称")
+
+ createResp, err := this.RPC().MonitorNodeRPC().CreateMonitorNode(this.AdminContext(), &pb.CreateMonitorNodeRequest{
+ Name: params.Name,
+ Description: params.Description,
+ IsOn: params.IsOn,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ // 创建日志
+ defer this.CreateLog(oplogs.LevelInfo, "创建监控节点 %d", createResp.NodeId)
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/helper.go b/internal/web/actions/default/settings/monitor-nodes/node/helper.go
new file mode 100644
index 00000000..689a22cc
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/helper.go
@@ -0,0 +1,21 @@
+package node
+
+import (
+ "github.com/iwind/TeaGo/actions"
+ "net/http"
+)
+
+type Helper struct {
+}
+
+func NewHelper() *Helper {
+ return &Helper{}
+}
+
+func (this *Helper) BeforeAction(action *actions.ActionObject) (goNext bool) {
+ if action.Request.Method != http.MethodGet {
+ return true
+ }
+
+ return true
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/index.go b/internal/web/actions/default/settings/monitor-nodes/node/index.go
new file mode 100644
index 00000000..4c3f5e32
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/index.go
@@ -0,0 +1,39 @@
+package node
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) Init() {
+ this.Nav("", "", "index")
+}
+
+func (this *IndexAction) RunGet(params struct {
+ NodeId int64
+}) {
+ nodeResp, err := this.RPC().MonitorNodeRPC().FindEnabledMonitorNode(this.AdminContext(), &pb.FindEnabledMonitorNodeRequest{NodeId: params.NodeId})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ node := nodeResp.Node
+ if node == nil {
+ this.NotFound("monitorNode", params.NodeId)
+ return
+ }
+
+ this.Data["node"] = maps.Map{
+ "id": node.Id,
+ "name": node.Name,
+ "description": node.Description,
+ "isOn": node.IsOn,
+ }
+
+ this.Show()
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/init.go b/internal/web/actions/default/settings/monitor-nodes/node/init.go
new file mode 100644
index 00000000..7b3800a5
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/init.go
@@ -0,0 +1,25 @@
+package node
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
+ Helper(settingutils.NewAdvancedHelper("monitorNodes")).
+ Prefix("/settings/monitorNodes/node").
+
+ // 节点相关
+ Helper(NewHelper()).
+ Get("", new(IndexAction)).
+ GetPost("/update", new(UpdateAction)).
+ Get("/install", new(InstallAction)).
+
+ EndAll()
+ })
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/install.go b/internal/web/actions/default/settings/monitor-nodes/node/install.go
new file mode 100644
index 00000000..a815528c
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/install.go
@@ -0,0 +1,57 @@
+package node
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/maps"
+ "strings"
+)
+
+type InstallAction struct {
+ actionutils.ParentAction
+}
+
+func (this *InstallAction) Init() {
+ this.Nav("", "", "install")
+}
+
+func (this *InstallAction) RunGet(params struct {
+ NodeId int64
+}) {
+ // 监控节点信息
+ nodeResp, err := this.RPC().MonitorNodeRPC().FindEnabledMonitorNode(this.AdminContext(), &pb.FindEnabledMonitorNodeRequest{NodeId: params.NodeId})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ node := nodeResp.Node
+ if node == nil {
+ this.NotFound("monitorNode", params.NodeId)
+ return
+ }
+
+ this.Data["node"] = maps.Map{
+ "id": node.Id,
+ "name": node.Name,
+ "uniqueId": node.UniqueId,
+ "secret": node.Secret,
+ }
+
+ // 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.Show()
+}
diff --git a/internal/web/actions/default/settings/monitor-nodes/node/update.go b/internal/web/actions/default/settings/monitor-nodes/node/update.go
new file mode 100644
index 00000000..1fa4376c
--- /dev/null
+++ b/internal/web/actions/default/settings/monitor-nodes/node/update.go
@@ -0,0 +1,73 @@
+package node
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
+ "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"
+)
+
+type UpdateAction struct {
+ actionutils.ParentAction
+}
+
+func (this *UpdateAction) Init() {
+ this.Nav("", "", "update")
+}
+
+func (this *UpdateAction) RunGet(params struct {
+ NodeId int64
+}) {
+ nodeResp, err := this.RPC().MonitorNodeRPC().FindEnabledMonitorNode(this.AdminContext(), &pb.FindEnabledMonitorNodeRequest{
+ NodeId: params.NodeId,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ node := nodeResp.Node
+ if node == nil {
+ this.WriteString("要操作的节点不存在")
+ return
+ }
+
+ this.Data["node"] = maps.Map{
+ "id": node.Id,
+ "name": node.Name,
+ "description": node.Description,
+ "isOn": node.IsOn,
+ }
+
+ this.Show()
+}
+
+// 保存基础设置
+func (this *UpdateAction) RunPost(params struct {
+ NodeId int64
+ Name string
+ Description string
+ IsOn bool
+
+ Must *actions.Must
+}) {
+ params.Must.
+ Field("name", params.Name).
+ Require("请输入监控节点名称")
+
+ _, err := this.RPC().MonitorNodeRPC().UpdateMonitorNode(this.AdminContext(), &pb.UpdateMonitorNodeRequest{
+ NodeId: params.NodeId,
+ Name: params.Name,
+ Description: params.Description,
+ IsOn: params.IsOn,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ // 创建日志
+ defer this.CreateLog(oplogs.LevelInfo, "修改监控节点 %d", params.NodeId)
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/settings/settingutils/advanced_helper.go b/internal/web/actions/default/settings/settingutils/advanced_helper.go
index bb4e0156..37fdd6df 100644
--- a/internal/web/actions/default/settings/settingutils/advanced_helper.go
+++ b/internal/web/actions/default/settings/settingutils/advanced_helper.go
@@ -34,6 +34,8 @@ func (this *AdvancedHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNex
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
tabbar.Add("用户节点", "", "/settings/userNodes", "", this.tab == "userNodes")
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
+ tabbar.Add("监控节点", "", "/settings/monitorNodes", "", this.tab == "monitorNodes")
+
//tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
}
actionutils.SetTabbar(actionPtr, tabbar)
diff --git a/internal/web/import.go b/internal/web/import.go
index 9dff3089..ebf60ec0 100644
--- a/internal/web/import.go
+++ b/internal/web/import.go
@@ -88,6 +88,8 @@ import (
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/database"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ip-library"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/login"
+ _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/monitor-nodes"
+ _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/monitor-nodes/node"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/profile"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/security"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/server"
diff --git a/web/views/@default/settings/monitor-nodes/index.html b/web/views/@default/settings/monitor-nodes/index.html
new file mode 100644
index 00000000..9283a3bc
--- /dev/null
+++ b/web/views/@default/settings/monitor-nodes/index.html
@@ -0,0 +1,49 @@
+{$layout}
+
+
暂时还没有节点。
+ +| 节点名称 | +版本号 | +CPU | +内存 | +状态 | +操作 | +
|---|---|---|---|---|---|
| {{node.name}} | ++ v{{node.status.buildVersion}} + - + | ++ {{node.status.cpuUsageText}} + - + | ++ {{node.status.memUsageText}} + - + | +
+
+ 运行中
+
+ 已断开
+ 未连接
+ |
+ + 详情 + 删除 + | +
| 节点名称 | ++ {{node.name}} + | +
| 状态 | +
+ |
+
| 描述 | ++ {{node.description}} + 暂时还没有描述。 + | +
| configs/api.yaml |
+
+ rpc:
+ endpoints: [ {{apiEndpoints}} ]
+nodeId: "{{node.uniqueId}}"
+secret: "{{node.secret}}"
+ |
+