package controller import ( "fmt" "os" "path/filepath" "runtime" "strings" "be.ems/src/framework/i18n" "be.ems/src/framework/utils/ctx" "be.ems/src/framework/utils/file" "be.ems/src/framework/utils/generate" "be.ems/src/framework/utils/ssh" "be.ems/src/framework/vo/result" neService "be.ems/src/modules/network_element/service" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" ) // 实例化控制层 NeActionController 结构体 var NewNeAction = &NeActionController{ neInfoService: neService.NewNeInfoImpl, } // 网元处理请求 // // PATH /action type NeActionController struct { // 网元信息服务 neInfoService neService.INeInfo } // 发送文件从本地到网元 // // POST /pushFile func (s *NeActionController) PushFile(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` NeID string `json:"neId" binding:"required"` UploadPath string `json:"uploadPath" binding:"required"` DelTemp bool `json:"delTemp"` // 删除本地临时文件 } if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID) if neInfo.NeId != body.NeID || neInfo.IP == "" { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } // 网元主机的SSH客户端 sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer sshClient.Close() // 网元主机的SSH客户端进行文件传输 sftpClient, err := sshClient.NewClientSFTP() if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer sftpClient.Close() // 本地文件 localFilePath := file.ParseUploadFilePath(body.UploadPath) // 网元端临时目录 sshClient.RunCMD("mkdir -p /tmp/omc/push && sudo chmod 777 -R /tmp/omc") neFilePath := filepath.ToSlash(filepath.Join("/tmp/omc/push", filepath.Base(localFilePath))) // 复制到远程 if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil { c.JSON(200, result.ErrMsg("Please check if the file exists or if scp is allowed to copy remotely")) return } defer func() { if body.DelTemp { _ = os.Remove(localFilePath) } }() c.JSON(200, result.OkData(filepath.ToSlash(neFilePath))) } // 获取文件从网元到本地 // // GET /pullFile func (s *NeActionController) PullFile(c *gin.Context) { language := ctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType" binding:"required"` NeID string `form:"neId" binding:"required"` Path string `form:"path" binding:"required"` FileName string `form:"fileName" binding:"required"` DelTemp bool `form:"delTemp"` // 删除本地临时文件 } if err := c.ShouldBindQuery(&querys); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) if neInfo.NeId != querys.NeID || neInfo.IP == "" { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } // 网元主机的SSH客户端 sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer sshClient.Close() // 网元主机的SSH客户端进行文件传输 sftpClient, err := sshClient.NewClientSFTP() if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer sftpClient.Close() nePath := filepath.ToSlash(filepath.Join(querys.Path, querys.FileName)) fileName := generate.Code(6) + "_" + querys.FileName localFilePath := filepath.Join("/tmp/omc/pull", fileName) if runtime.GOOS == "windows" { localFilePath = fmt.Sprintf("C:%s", localFilePath) } // 复制到本地 if err = sftpClient.CopyFileRemoteToLocal(nePath, localFilePath); err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer func() { if querys.DelTemp { _ = os.Remove(localFilePath) } }() c.FileAttachment(localFilePath, fileName) } // 网元端文件列表 // // GET /files func (s *NeActionController) Files(c *gin.Context) { language := ctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType" binding:"required"` NeID string `form:"neId" binding:"required"` Path string `form:"path" binding:"required"` PageNum int64 `form:"pageNum" binding:"required"` PageSize int64 `form:"pageSize" binding:"required"` Search string `form:"search"` } if err := c.ShouldBindQuery(&querys); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) if neInfo.NeId != querys.NeID || neInfo.IP == "" { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } // 网元主机的SSH客户端 sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } defer sshClient.Close() // 获取文件列表 rows, err := ssh.FileList(sshClient, querys.Path, querys.Search) if err != nil { c.JSON(200, result.Ok(map[string]any{ "path": querys.Path, "total": len(rows), "rows": []ssh.FileListRow{}, })) return } // 对数组进行切片分页 lenNum := int64(len(rows)) start := (querys.PageNum - 1) * querys.PageSize end := start + querys.PageSize var splitRows []ssh.FileListRow if start >= lenNum { splitRows = []ssh.FileListRow{} } else if end >= lenNum { splitRows = rows[start:] } else { splitRows = rows[start:end] } c.JSON(200, result.Ok(map[string]any{ "path": querys.Path, "total": lenNum, "rows": splitRows, })) } // 网元服务操作 // // PUT /service func (s *NeActionController) Service(c *gin.Context) { language := ctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` NeID string `json:"neId" binding:"required"` Action string `json:"action" binding:"required,oneof=start restart stop reboot poweroff"` // 操作行为 } if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID) if neInfo.NeId != body.NeID || neInfo.IP == "" { c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } neTypeLower := strings.ToLower(neInfo.NeType) cmdStr := fmt.Sprintf("sudo service %s %s", neTypeLower, body.Action) if neTypeLower == "omc" { cmdStr = fmt.Sprintf("nohup sh -c \"sudo systemctl stop restagent && sleep 5s && sudo systemctl %s restagent\" > /dev/null 2>&1 &", body.Action) } else if neTypeLower == "ims" { if body.Action == "restart" { cmdStr = "ims-stop || true && ims-start" } else { cmdStr = fmt.Sprintf("sudo ims-%s", body.Action) } } if body.Action == "reboot" { cmdStr = "sudo shutdown -r now" } if body.Action == "poweroff" { cmdStr = "sudo shutdown -h now" } _, err := s.neInfoService.NeRunSSHCmd(body.NeType, body.NeID, cmdStr) if err != nil { c.JSON(200, result.ErrMsg(err.Error())) return } c.JSON(200, result.Ok(nil)) }