package controller import ( "strings" "be.ems/src/framework/i18n" "be.ems/src/framework/utils/ctx" "be.ems/src/framework/utils/parse" "be.ems/src/framework/utils/ssh" "be.ems/src/framework/utils/telnet" "be.ems/src/framework/vo/result" "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" ) // 实例化控制层 NeHostController 结构体 var NewNeHost = &NeHostController{ neHostService: neService.NewNeHostImpl, } // 网元主机连接请求 // // PATH /host type NeHostController struct { // 网元主机连接服务 neHostService neService.INeHost } // 网元主机列表 // // GET /list func (s *NeHostController) List(c *gin.Context) { querys := ctx.QueryMap(c) data := s.neHostService.SelectPage(querys) rows := data["rows"].([]model.NeHost) arr := &rows for i := range *arr { (*arr)[i].Password = "-" (*arr)[i].PrivateKey = "-" (*arr)[i].PassPhrase = "-" } c.JSON(200, result.Ok(data)) } // 网元主机信息 // // GET /:hostId func (s *NeHostController) Info(c *gin.Context) { language := ctx.AcceptLanguage(c) hostId := c.Param("hostId") if hostId == "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } neHost := s.neHostService.SelectById(hostId) if neHost.HostID != hostId { // 没有可访问主机信息数据! c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.noData"))) return } c.JSON(200, result.OkData(neHost)) } // 网元主机新增 // // POST / func (s *NeHostController) Add(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeHost err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil || body.HostID != "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查属性值唯一 uniqueHost := s.neHostService.CheckUniqueHostTitle(body.GroupID, body.Title, body.HostType, "") if !uniqueHost { // 主机信息操作【%s】失败,同组内名称已存在 msg := i18n.TTemplate(language, "neHost.errKeyExists", map[string]any{"name": body.Title}) c.JSON(200, result.ErrMsg(msg)) return } body.CreateBy = ctx.LoginUserToUserName(c) insertId := s.neHostService.Insert(body) if insertId != "" { c.JSON(200, result.Ok(nil)) return } c.JSON(200, result.Err(nil)) } // 网元主机修改 // // PUT / func (s *NeHostController) Edit(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeHost err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil || body.HostID == "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查属性值唯一 uniqueHost := s.neHostService.CheckUniqueHostTitle(body.GroupID, body.Title, body.HostType, body.HostID) if !uniqueHost { // 主机信息操作【%s】失败,同组内名称已存在 msg := i18n.TTemplate(language, "neHost.errKeyExists", map[string]any{"name": body.Title}) c.JSON(200, result.ErrMsg(msg)) return } // 检查是否存在 neHost := s.neHostService.SelectById(body.HostID) if neHost.HostID != body.HostID { // 没有可访问主机信息数据! c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.noData"))) return } body.UpdateBy = ctx.LoginUserToUserName(c) rows := s.neHostService.Update(body) if rows > 0 { c.JSON(200, result.Ok(nil)) return } c.JSON(200, result.Err(nil)) } // 网元主机删除 // // DELETE /:hostIds func (s *NeHostController) Remove(c *gin.Context) { language := ctx.AcceptLanguage(c) hostIds := c.Param("hostIds") if hostIds == "" { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 处理字符转id数组后去重 ids := strings.Split(hostIds, ",") uniqueIDs := parse.RemoveDuplicates(ids) if len(uniqueIDs) <= 0 { c.JSON(200, result.Err(nil)) return } rows, err := s.neHostService.DeleteByIds(uniqueIDs) if err != nil { c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) return } msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) c.JSON(200, result.OkMsg(msg)) } // 网元主机测试连接 // // POST /test func (s *NeHostController) Test(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeHost err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } if body.HostType == "ssh" { var connSSH ssh.ConnSSH body.CopyTo(&connSSH) client, err := connSSH.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() c.JSON(200, result.Ok(nil)) return } if body.HostType == "telnet" { var connTelnet telnet.ConnTelnet body.CopyTo(&connTelnet) client, err := connTelnet.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() c.JSON(200, result.Ok(nil)) return } } // 网元主机发送命令 // // POST /cmd func (s *NeHostController) Cmd(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { HostID string `json:"hostId" binding:"required"` // 主机ID Cmd string `json:"cmd" binding:"required"` // 执行命令 } err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 检查是否存在 neHost := s.neHostService.SelectById(body.HostID) if neHost.HostID != body.HostID { // 没有可访问主机信息数据! c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.noData"))) return } if neHost.HostType == "ssh" { var connSSH ssh.ConnSSH neHost.CopyTo(&connSSH) client, err := connSSH.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() // 执行命令 output, err := client.RunCMD(body.Cmd) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } c.JSON(200, result.OkData(output)) return } if neHost.HostType == "telnet" { var connTelnet telnet.ConnTelnet neHost.CopyTo(&connTelnet) client, err := connTelnet.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() // 执行命令 output, err := client.RunCMD(body.Cmd) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } c.JSON(200, result.OkData(output)) return } } // 网元主机SSH方式检查服务器环境 // // POST /checkBySSH func (s *NeHostController) CheckBySSH(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeHost err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } var connSSH ssh.ConnSSH body.CopyTo(&connSSH) // 创建链接SSH客户端 client, err := connSSH.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() // 结果信息数据 data := map[string]any{ "addr": body.Addr, // 服务器地址 "kernelName": "-", // 内核名称 -s "nodename": "-", // 网络节点主机名 -n "kernelRelease": "-", // 内核发布版本 -r "machine": "-", // 机器硬件名称 -m "prettyName": "-", // 系统发行版本 "sudo": false, // 可提权 "sshLink": false, // 可直连 } // 执行命令 检查系统环境 output, err := client.RunCMD("uname -snrm && cat /etc/os-release | grep PRETTY_NAME") if err != nil { c.JSON(200, result.OkData(data)) return } output = strings.TrimSuffix(output, "\n") sysInfoArr := strings.SplitN(output, "\n", 2) if len(sysInfoArr) == 2 { // uname -snrm baseInfoArr := strings.SplitN(sysInfoArr[0], " ", 4) data["kernelName"] = baseInfoArr[0] data["nodename"] = baseInfoArr[1] data["kernelRelease"] = baseInfoArr[2] data["machine"] = baseInfoArr[3] // cat /etc/os-release | grep PRETTY_NAME prettyName := sysInfoArr[1] index := strings.Index(prettyName, `"`) if index != -1 { data["prettyName"] = prettyName[index+1 : len(prettyName)-1] } } // 执行命令 检查sudo权限 _, err = client.RunCMD("sudo -n uname") if err == nil { data["sudo"] = true } else { data["sudo"] = false } // 本地免密创建链接直连 lcoalConnSSH := ssh.ConnSSH{ User: body.User, Addr: body.Addr, Port: body.Port, } lcoalClient, err := lcoalConnSSH.NewClientByLocalPrivate() if err == nil { data["sshLink"] = true } else { data["sshLink"] = false } defer lcoalClient.Close() c.JSON(200, result.OkData(data)) } // 网元主机SSH方式授权免密发送 // // POST /authorizedBySSH func (s *NeHostController) AuthorizedBySSH(c *gin.Context) { language := ctx.AcceptLanguage(c) var body model.NeHost err := c.ShouldBindBodyWith(&body, binding.JSON) if err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 本地免密创建链接直连 sshLink := false lcoalConnSSH := ssh.ConnSSH{ User: body.User, Addr: body.Addr, Port: body.Port, } lcoalClient, err := lcoalConnSSH.NewClientByLocalPrivate() if err == nil { sshLink = true } defer lcoalClient.Close() if sshLink { // 连接主机成功,无需重复免密授权认证 c.JSON(200, result.OkMsg(i18n.TKey(language, "neHost.okBySSHLink"))) return } // 创建链接SSH客户端 var connSSH ssh.ConnSSH body.CopyTo(&connSSH) client, err := connSSH.NewClient() if err != nil { // 连接主机失败,请检查连接参数后重试 c.JSON(200, result.ErrMsg(i18n.TKey(language, "neHost.errByHostInfo"))) return } defer client.Close() // 发送密钥 err = client.SendToAuthorizedKeys() if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } c.JSON(200, result.Ok(nil)) }