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}} + - + + +
+ 运行中 +
+ 已断开 + 未连接 +
+ 详情   + 删除 +
+ +
\ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/index.js b/web/views/@default/settings/monitor-nodes/index.js new file mode 100644 index 00000000..1d8f4319 --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/index.js @@ -0,0 +1,26 @@ +Tea.context(function () { + // 创建节点 + this.createNode = function () { + teaweb.popup("/settings/monitorNodes/node/createPopup", { + width: "50em", + height: "30em", + callback: function () { + teaweb.success("保存成功", function () { + teaweb.reload() + }) + } + }) + } + + // 删除节点 + this.deleteNode = function (nodeId) { + let that = this + teaweb.confirm("确定要删除此节点吗?", function () { + that.$post("/settings/monitorNodes/delete") + .params({ + nodeId: nodeId + }) + .refresh() + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/node/@menu.html b/web/views/@default/settings/monitor-nodes/node/@menu.html new file mode 100644 index 00000000..395e1b5d --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/@menu.html @@ -0,0 +1,7 @@ + + 节点列表 + | + "{{node.name}}"详情 + 安装节点 + 修改节点 + diff --git a/web/views/@default/settings/monitor-nodes/node/createPopup.html b/web/views/@default/settings/monitor-nodes/node/createPopup.html new file mode 100644 index 00000000..e7afb04b --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/createPopup.html @@ -0,0 +1,34 @@ +{$layout "layout_popup"} + +

添加监控节点

+
+ + + + + + + + + + + + + + + + + + +
节点名称 * + +
描述 + +
是否启用 +
+ + +
+
+ +
\ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/node/createPopup.js b/web/views/@default/settings/monitor-nodes/node/createPopup.js new file mode 100644 index 00000000..c6471490 --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/createPopup.js @@ -0,0 +1,3 @@ +Tea.context(function () { + +}) \ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/node/index.html b/web/views/@default/settings/monitor-nodes/node/index.html new file mode 100644 index 00000000..fb9a5f7b --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/index.html @@ -0,0 +1,24 @@ +{$layout} +{$template "menu"} + + + + + + + + + + + + + + +
节点名称 + {{node.name}} +
状态 + +
描述 + {{node.description}} + 暂时还没有描述。 +
\ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/node/install.html b/web/views/@default/settings/monitor-nodes/node/install.html new file mode 100644 index 00000000..2073f44d --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/install.html @@ -0,0 +1,23 @@ +{$layout} +{$template "menu"} + +

安装步骤

+
    +
  1. 按照下面的配置信息替换configs/api.yaml内容
  2. +
  3. 使用bin/edge-monitor start启动节点
  4. +
  5. 可以在logs/run.log中查看启动是否有异常
  6. +
+ +
+

配置信息

+ + + + + +
configs/api.yaml
[下载]
+
rpc:
+  endpoints: [ {{apiEndpoints}} ]
+nodeId: "{{node.uniqueId}}"
+secret: "{{node.secret}}"
+
diff --git a/web/views/@default/settings/monitor-nodes/node/update.html b/web/views/@default/settings/monitor-nodes/node/update.html new file mode 100644 index 00000000..401969a1 --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/update.html @@ -0,0 +1,37 @@ +{$layout} + +{$template "menu"} + +
+ + + + + + + + + + + + + + + + + + + + +
节点名称 * + +
描述 + +
是否启用 +
+ + +
+
+ +
\ No newline at end of file diff --git a/web/views/@default/settings/monitor-nodes/node/update.js b/web/views/@default/settings/monitor-nodes/node/update.js new file mode 100644 index 00000000..08078f45 --- /dev/null +++ b/web/views/@default/settings/monitor-nodes/node/update.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.success = NotifySuccess("保存成功", "/settings/monitorNodes/node?nodeId=" + this.node.id) +}) \ No newline at end of file